☰
Godot Array 类型完全指南:动态数组、类型化数组与函数式操作实战(godot-docs)
2026/10/3 2:28:11 网站建设 项目流程
  • 文档
  • 教程
  • 游戏开发

【免费下载链接】godot-docs

Godot Engine official documentation

项目地址:https://gitcode.com/GitHub_Trending/go/godot-docs
点击查看免费下载

Array 是 Godot 内置的核心容器类型,用于保存任意 Variant 元素的序列。本文以 class_array.rst 官方类参考为骨架,结合 GDScript 基础 与 C# 集合对照 等仓库资料,系统讲解 Array 的构造、索引、全部 49 个方法、运算符语义、类型化数组与压缩数组的取舍,以及遍历与复制时的注意事项,帮助你写出正确、高效、可维护的数组代码。

Array 是什么

Array 是一种内置数据结构,默认情况下可以容纳任意 Variant 类型的元素序列。通过创建typed array(类型化数组),可以将值约束为特定类型。元素通过从0开始的数值索引访问;负索引从尾部倒数(-1是最后一个元素,-2是倒数第二个,以此类推)。

var array = ["First", 2, 3, "Last"] print(array[0]) # Prints "First" print(array[2]) # Prints 3 print(array[-1]) # Prints "Last" array[1] = "Second" print(array[1]) # Prints "Second" print(array[-3]) # Prints "Second" # 这个类型化数组只能包含整数。 # 尝试添加任何其他类型都会报错。 var typed_array: Array[int] = [1, 2, 3]

C# 中对应Godot.Collections.Array,索引语义一致(^1表示最后一个元素),类型化数组写作Godot.Collections.Array<int>:

Godot.Collections.Array array = ["First", 2, 3, "Last"]; GD.Print(array[0]); // Prints "First" GD.Print(array[2]); // Prints 3 GD.Print(array[^1]); // Prints "Last" array[1] = "Second"; GD.Print(array[1]); // Prints "Second" GD.Print(array[^3]); // Prints "Second" // 这个类型化数组只能包含整数。 Godot.Collections.Array<int> typedArray = [1, 2, 3];

三个必须牢记的核心语义

1. 按引用传递

Array 总是按引用(reference)传递。如果你希望获得一个可独立于原数组修改的副本,必须使用duplicate()(详见"复制与切片"一节)。直接赋值var b = a只是让b与a指向同一个底层结构。

2. 迭代期间禁止删除元素

在遍历数组的同时擦除(erase)元素是不被支持的,会导致不可预测的行为。如果你需要在迭代中修改内容,官方建议改用for i in array.size()配合索引赋值(见 gdscript_basics.rst 的 for 循环说明)。

3. 布尔上下文中的求值规则

在布尔上下文中,空数组[]求值为false,非空数组始终求值为true。这在编写if my_array:这类条件判断时需要留意——它判断的是"是否为空",而不是"是否有某个元素"。

三种数组类型:压缩数组、类型化数组、非类型化数组

类型迭代/修改速度内存灵活性
压缩数组(Packed Array)一般最快最小最低,缺少map()等便捷方法
类型化数组(Typed Array)较快中等中等,元素类型受限
非类型化数组(Untyped Array)较慢较大最高

原文档明确指出:压缩数组通常比同类型数组(如 PackedInt64Array 对比Array[int])迭代和修改更快、占用内存更少;其代价是灵活性低,不提供map()这类便捷方法。类型化数组又比非类型化数组迭代和修改更快。

gdscript_basics.rst 的 Packed arrays 小节 进一步补充了选型建议:

  • 当数组足够大(成千上万个元素)且数据类型与某个Packed类型匹配时,使用压缩数组可同时改善内存占用与迭代/修改性能;
  • 若数组规模不大(如远未达到数万元素),常规或类型化数组提供的便捷方法更利于编写和维护;
  • 数据是已知类型(包括自定义类)时,优先使用类型化数组。

类型化数组的 GDScript 语法为Array[Type],Type可以是任意 Variant 类型、原生类、用户类或枚举;不支持嵌套数组类型(如Array[Array[int]])。Array与Array[Variant]等价。类型化数组的类型是内存结构的一个属性,因此不能把Array[Node2D]直接赋给Array[Node]变量(即使 Node2D 是 Node 的子类);需要转换时用assign()方法复制内容而非引用:

var a: Array[Node2D] = [Node2D.new()] # (OK) Node2D 继承自 Node,可以放入 Array[Node] var b: Array[Node] = [a[0]] # (Error) 不能将 Array[Node2D] 赋给 Array[Node] 变量 # b = a # (OK) 用 assign() 复制内容而不是引用 b.assign(a)

唯一的例外是Array(即Array[Variant])类型,这是为兼容旧代码做的便利设计——但对非类型化数组的操作被视为不安全操作。另外注意,类型化数组目前在可变参数(variadic)函数中不受支持,无法写出...values: Array[int]。

构造函数

Array():构造空数组

构造一个空的 Array。

Array(base, type, class_name, script):从 base 构造类型化数组

从base数组创建类型化数组。类型化数组只能包含给定类型的元素,或继承自给定类的元素。参数含义:

  • type:内置 Variant 类型,取 Variant.Type 枚举常量之一;
  • class_name:内置类名(参见 Object.get_class());
  • script:关联的脚本,必须是 Script 实例或null。

如果type不是TYPE_OBJECT,则class_name必须为空StringName、script必须为null。

class_name Sword extends Node class Stats: pass func _ready(): var a = Array([], TYPE_INT, "", null) # Array[int] var b = Array([], TYPE_OBJECT, "Node", null) # Array[Node] var c = Array([], TYPE_OBJECT, "Node", Sword) # Array[Sword] var d = Array([], TYPE_OBJECT, "RefCounted", Stats) # Array[Stats]

base数组的元素会在必要时进行转换。如果无法转换,或base本身已是类型化数组,则构造失败并返回空 Array。

在 GDScript 中通常不需要这个构造函数,静态类型即可创建类型化数组:

var numbers: Array[float] = [] var children: Array[Node] = [$Node, $Sprite2D, $RigidBody3D] # 浮点字面量会被转换为整数 var integers: Array[int] = [0.2, 4.5, -2.0] print(integers) # Prints [0, 4, -2]

Array(from: Array):返回同一数组

返回与from相同的数组(引用,非副本)。需要副本请用duplicate()。

从压缩数组构造

Array(from: PackedByteArray)、Array(from: PackedColorArray)、Array(from: PackedFloat32Array)、Array(from: PackedFloat64Array)、Array(from: PackedInt32Array)、Array(from: PackedInt64Array)、Array(from: PackedStringArray)、Array(from: PackedVector2Array)、Array(from: PackedVector3Array)、Array(from: PackedVector4Array):分别从对应的压缩数组构造普通数组。这是压缩数组与普通数组互转的官方入口之一。

元素的增删改:核心增删方法

方法签名要点行为
append(value)push_back()的别名在数组末尾追加value
append_array(array)—将另一个array追加到本数组末尾
push_back(value)—在末尾追加一个元素
push_front(value)—在开头添加一个元素,会移动所有其他元素的索引,大数组上有明显性能开销
insert(position, value)返回 Error在position(可为负数,相对末尾)插入元素,返回OK或错误常量;position之后的索引都要前移,大数组开销明显
erase(value)按值删除找到并移除value的第一次出现;不存在则什么都不做;删除后所有后续索引回移
remove_at(position)按下标删除删除position处元素,负数相对末尾,越界会失败;需要返回值用pop_at(),按值删除用erase()
pop_back()删除并返回移除并返回最后一个元素;空数组返回null且不报错
pop_front()删除并返回移除并返回第一个元素;空数组返回null且不报错;其余元素索引回移
pop_at(position)删除并返回移除并返回position处元素,负数相对末尾;空数组返回null,越界会生成错误信息
clear()清空移除所有元素,等价于resize(0)
resize(size)调整大小设为size个元素;缩小则删除末尾,扩大则添加默认元素(通常为null,取决于数组类型)。返回OK、ERR_LOCKED(只读数组)、ERR_INVALID_PARAMETER(size 为负)或ERR_OUT_OF_MEMORY。一次性resize后赋值比逐个append更快
fill(value)批量赋值将value赋给所有元素;常与resize()组合使用
set(index, value)按下标赋值与array[index] = value等价,不改变数组大小
assign(array)整体赋值把另一数组的元素复制进本数组,按需 resize;类型化数组会执行类型转换

append_array示例:

var numbers = [1, 2, 3] var extra = [4, 5, 6] numbers.append_array(extra) print(numbers) # Prints [1, 2, 3, 4, 5, 6]

resize+fill组合(GDScript 与 C# 对照):

var array = [] array.resize(5) array.fill(2) print(array) # Prints [2, 2, 2, 2, 2]
Godot.Collections.Array array = []; array.Resize(5); array.Fill(2); GD.Print(array); // Prints [2, 2, 2, 2, 2]

注意:如果fill()的value是引用类型 Variant(继承自 Object、Array、Dictionary 等),数组会被填充为对同一个 value 的引用,而不是副本。

查询与搜索:find 系列与成员检查

方法说明
size()返回元素个数,空数组返回0
is_empty()返回true当且仅当数组为空
has(value)返回是否包含value(GDScript 等价于in操作符;C# 中改名为Contains)
count(value)返回value在数组中出现的次数;按条件计数请用reduce()
find(what, from = 0)返回what第一次出现的索引,无则返回-1;from指定搜索起点
rfind(what, from = -1)返回what最后一次出现的索引,无则返回-1;find()的逆向版本
find_custom(callable, from = 0)返回第一个使callable返回true的元素索引,无则-1
rfind_custom(callable, from = -1)从后向前查找第一个满足callable的元素索引
front()返回第一个元素;空数组失败并返回null(与array[0]不同,只产生错误不中断项目执行)
back()返回最后一个元素;空数组失败并返回null(与array[-1]不同)
get(index)返回index处元素;越界或负索引失败并返回null。与[]操作符类似但不完全相同:失败时不会在编辑器中暂停项目执行
min()所有元素可比较时返回最小值,否则返回null
max()所有元素可比较时返回最大值,否则返回null;自定义比较器可用reduce()实现
pick_random()返回随机一个元素;空数组报错并返回null
hash()返回代表数组及其内容的 32 位哈希整数。哈希值相同的数组不一定相同(哈希碰撞),哈希值不同的数组必然不同

has()与in操作符示例:

print(["inside", 7].has("inside")) # Prints true print(["inside", 7].has("outside")) # Prints false print(["inside", 7].has(7)) # Prints true print(["inside", 7].has("7")) # Prints false if 4 in [2, 4, 6, 8]: print("4 is here!") # Will be printed.

C# 对照(方法更名为Contains):

Godot.Collections.Array arr = ["inside", 7]; GD.Print(arr.Contains("inside")); // Prints True GD.Print(arr.Contains("outside")); // Prints False GD.Print(arr.Contains(7)); // Prints True GD.Print(arr.Contains("7")); // Prints False

性能注意:出于性能考虑,find()/has()的搜索会受到what的Variant.Type影响。例如7(int)和7.0(float)对这两个方法而言不相等。

find_custom配合bind()传递额外参数:

func is_even(number): return number % 2 == 0 func _ready(): print([1, 3, 4, 7].find_custom(is_even.bind())) # Prints 2 func is_specific_number(number, expected): return number == expected func _ready(): print([1, 3, 4, 7].find_custom(is_specific_number.bind(4))) # Prints 2

函数式方法:map / filter / reduce / all / any

这四个方法是函数式编程风格的支柱,callable通常只接收当前数组元素一个参数(reduce例外,接收两个)。

map(callable):映射

对每个元素调用callable,返回由返回值组成的新数组。callable接收一个元素参数,可返回任意 Variant。

func double(number): return number * 2 func _ready(): print([1, 2, 3].map(double)) # Prints [2, 4, 6] # 同样效果,使用 lambda 函数 print([1, 2, 3].map(func(element): return element * 2))

filter(callable):过滤

对每个元素调用callable,返回新过滤数组。callable返回true则保留该元素,false则排除。

func is_even(number): return number % 2 == 0 func _ready(): print([1, 4, 5, 8].filter(is_even)) # Prints [4, 8] # 同样效果,使用 lambda 函数 print([1, 4, 5, 8].filter(func(number): return number % 2 == 0))

reduce(callable, accum = null):归约

对每个元素调用callable,将结果累积到accum并返回。callable接收两个参数:当前累积值accum和当前元素。若accum为null(默认),迭代从第二个元素开始,第一个元素作为accum的初始值。

func sum(accum, number): return accum + number func _ready(): print([1, 2, 3].reduce(sum, 0)) # Prints 6 print([1, 2, 3].reduce(sum, 10)) # Prints 16 # lambda 写法 print([1, 2, 3].reduce(func(accum, number): return accum + number, 10))

reduce的三个高级用途——自定义比较器、按条件计数(替代count()):

# 自定义比较器:找出最长向量 func _ready(): var arr = [Vector2i(5, 0), Vector2i(3, 4), Vector2i(1, 2)] var longest_vec = arr.reduce(func(max, vec): return vec if is_length_greater(vec, max) else max) print(longest_vec) # Prints (3, 4) func is_length_greater(a, b): return a.length() > b.length() # 按条件计数 func is_even(number): return number % 2 == 0 func _ready(): var arr = [1, 2, 3, 4, 5] # 当前元素是偶数则计数加一,否则保持不变 var even_count = arr.reduce(func(count, next): return count + 1 if is_even(next) else count, 0) print(even_count) # Prints 2

all(callable)与any(callable):全称与存在性判断

  • all():对所有元素调用callable,全部返回true才返回true;有一个以上返回false即返回false。
  • any():至少一个元素使callable返回true即返回true;全部为false才返回false。

两者都支持 lambda。空数组语义不同:all()对空数组恒返回true(空真原则,vacuous truth),any()对空数组恒返回false。

func greater_than_5(number): return number > 5 func _ready(): print([6, 10, 6].all(greater_than_5)) # Prints true (3/3 个元素为 true) print([4, 10, 4].all(greater_than_5)) # Prints false (1/3 个元素为 true) print([4, 4, 4].all(greater_than_5)) # Prints false (0/3 个元素为 true) print([].all(greater_than_5)) # Prints true (0/0 个元素为 true) print([6, 10, 6].any(greater_than_5)) # Prints true (3 个元素为 true) print([4, 10, 4].any(greater_than_5)) # Prints true (1 个元素为 true) print([4, 4, 4].any(greater_than_5)) # Prints false (0 个元素为 true) print([].any(greater_than_5)) # Prints false (0 个元素为 true) # lambda 写法 print([6, 10, 6].all(func(element): return element > 5)) # Prints true print([6, 10, 6].any(func(number): return number > 5)) # Prints true

性能提示:与"用filter()结果的长度判断"相比,all()/any()会尽早返回以提升性能(尤其对大数组)。

排序

sort():升序排序

按元素的"小于"(<)比较升序排列。

var numbers = [10, 5, 2.5, 8] numbers.sort() print(numbers) # Prints [2.5, 5, 8, 10]
Godot.Collections.Array numbers = [10, 5, 2.5, 8]; numbers.Sort(); GD.Print(numbers); // Prints [2.5, 5, 8, 10]

注意:所用排序算法不稳定(not stable),等价元素(如2与2.0)的相对顺序可能被改变。

sort_custom(func):自定义排序

func按需被调用,接收两个元素作为参数;返回true表示第一个元素应排在第二个之前,返回false则反之。

func sort_ascending(a, b): if a[1] < b[1]: return true return false func _ready(): var my_items = [["Tomato", 5], ["Apple", 9], ["Rice", 4]] my_items.sort_custom(sort_ascending) print(my_items) # Prints [["Rice", 4], ["Tomato", 5], ["Apple", 9]] # lambda 写法,降序 my_items.sort_custom(func(a, b): return a[1] > b[1]) print(my_items) # Prints [["Apple", 9], ["Tomato", 5], ["Rice", 4]]

对文件名做自然顺序排序是sort_custom的典型场景,配合 String.naturalnocasecmp_to():

var files = ["newfile1", "newfile2", "newfile10", "newfile11"] files.sort_custom(func(a, b): return a.naturalnocasecmp_to(b) < 0) print(files) # Prints ["newfile1", "newfile2", "newfile10", "newfile11"]

使用注意:C# 中不支持sort_custom;排序算法不稳定;不要随机化func的返回值——堆排序算法要求一致的结果,随机化会导致意外行为。

二分搜索

bsearch(value, before = true)

在已排序数组上使用二分查找返回value的索引;找不到时返回应插入以保持有序的位置。before为true(默认)时,返回的索引位于所有与value相等的既有元素之前。

var numbers = [2, 4, 8, 10] var idx = numbers.bsearch(7) numbers.insert(idx, 7) print(numbers) # Prints [2, 4, 7, 8, 10] var fruits = ["Apple", "Lemon", "Lemon", "Orange"] print(fruits.bsearch("Lemon", true)) # Prints 1, 指向第一个 "Lemon" print(fruits.bsearch("Lemon", false)) # Prints 3, 指向 "Orange"

对未排序数组调用bsearch()会产生意外结果,务必先sort()。

bsearch_custom(value, func, before = true)

与bsearch()相同,但用func做比较。func接收一个数组元素和value两个参数,返回true表示该数组元素应排在value之后。

func sort_by_amount(a, b): if a[1] < b[1]: return true return false func _ready(): var my_items = [["Tomato", 2], ["Kiwi", 5], ["Rice", 9]] var apple = ["Apple", 5] # "Apple" 插入到 "Kiwi" 之前 my_items.insert(my_items.bsearch_custom(apple, sort_by_amount, true), apple) var banana = ["Banana", 5] # "Banana" 插入到 "Kiwi" 之后 my_items.insert(my_items.bsearch_custom(banana, sort_by_amount, false), banana) # Prints [["Tomato", 2], ["Apple", 5], ["Kiwi", 5], ["Banana", 5], ["Rice", 9]] print(my_items)

同样地,bsearch_custom要求数组已按func排序(可先用sort_custom(func)排序)。

复制与切片:duplicate / duplicate_deep / slice

duplicate(deep = false)

返回数组的新副本。默认浅拷贝:所有嵌套的 Array、Dictionary、Resource 元素与原数组共享,在一方修改会影响到另一方。deep为true时返回深拷贝:嵌套数组和字典被递归复制,但Resource 仍然共享。

duplicate_deep(deep_subresources_mode = 1)

类似duplicate(true)的深拷贝,但对子资源处理有额外控制。deep_subresources_mode必须是 Resource.DeepDuplicateMode 枚举的值;默认只递归复制内部资源。

slice(begin, end = INT_MAX, step = 1, deep = false)

返回包含从begin(含)到end(不含)元素的新数组,每隔step取一个。

  • begin/end为负时相对数组末尾;
  • step为负时反向迭代,返回倒序切片(此时begin必须大于end);
  • deep为true时递归复制切片中的嵌套 Array 与 Dictionary。
var letters = ["A", "B", "C", "D", "E", "F"] print(letters.slice(0, 2)) # Prints ["A", "B"] print(letters.slice(2, -2)) # Prints ["C", "D"] print(letters.slice(-2, 6)) # Prints ["E", "F"] print(letters.slice(0, 6, 2)) # Prints ["A", "C", "E"] print(letters.slice(4, 1, -1)) # Prints ["E", "D", "C"]

只读与类型信息查询

方法说明
is_read_only()返回数组是否为只读
make_read_only()将数组设为只读:元素不能被覆盖、顺序不能改变;不作用于嵌套元素(如字典)。GDScript 中声明为const的数组自动只读
is_typed()返回数组是否为类型化数组。类型化数组的方法仍返回通用 Variant
is_same_typed(array)返回本数组与给定array的类型化方式是否相同
get_typed_builtin()返回类型化数组的内置 Variant 类型常量;非类型化返回TYPE_NIL
get_typed_class_name()若内置类型为TYPE_OBJECT,返回类型化数组的内置类名;否则返回空 StringName
get_typed_script()返回与该类型化数组关联的 Script 实例;不存在返回null
var numbers: Array[float] = [0.2, 4.2, -2.0] print(numbers.is_typed()) # Prints true

此外还有reverse()(反转所有元素顺序)与shuffle()(随机打乱元素顺序)。shuffle()与pick_random()一样使用全局共享随机种子;要获得可预测的结果,可先调用 @GlobalScope.seed()。

# 可能打印 1、2、3.25 或 "Hi" print([1, 2, 3.25, "Hi"].pick_random())

运算符

运算符返回语义
array[index]Variant按索引取元素,索引 0 起;负数从尾部取;越界访问会产生运行时错误,在编辑器中会暂停项目执行
array1 + array2Array拼接:把右侧数组追加到左侧,产生新数组。对已有数组,append_array()比+/+=更高效
array1 == array2bool长度与内容全部相等才为true
array1 != array2bool长度或任一元素不同即为true
<、<=、>、>=bool从索引 0 起逐对比较,直到两个数组共同长度的末尾;逐对比较出大小即返回;若所有比较过的元素都相等,则由数组长度决定结果

运算符示例:

var array1 = ["One", 2] var array2 = [3, "Four"] print(array1 + array2) # Prints ["One", 2, 3, "Four"]

C# 中注意,原生Array类型不支持拼接,但Godot.Collections.Array支持:

Godot.Collections.Array array1 = ["One", 2]; Godot.Collections.Array array2 = [3, "Four"]; GD.Print(array1 + array2); // Prints ["One", 2, 3, "Four"]

遍历 Array:for 循环的正确姿势

gdscript_basics.rst 说明了遍历数组的两种方式:

var names = ["John", "Marta", "Samantha", "Jimmy"] for name: String in names: # 类型化循环变量 print(name) # 打印每个名字 # 如果要在迭代过程中赋值,最好用索引方式 for i in array.size(): array[i] = some_new_value(i)

for x in [5, 7, 11]:会把元素依次存入x。注意原文档反复强调的规则:不要在遍历数组的同时 erase/pop 元素,否则行为不可预测。同时记住range()不会分配数组,纯数字循环应优先用for i in range(n)。

C# 中的 Array 与压缩数组映射

Collections 指南 指出:尽管名字是 "Array",Godot Array 更接近 C# 的List<T>而非System.Array,其大小不固定、可随增删动态伸缩。

  • 未类型化的Godot.Collections.Array可等价看作Variant元素数组,能容纳任意类型;
  • 泛型Godot.Collections.Array<T>将元素类型限制为 Variant 兼容类型;
  • 未类型化数组可通过new Godot.Collections.Array<T>(untypedArray)构造函数转换为类型化数组;
  • GDScript 的压缩数组在 C# 中直接使用System.Array(byte[]、int[]、long[]、float[]、double[]、string[]、Vector2[]、Vector3[]、Vector4[]、Color[])。

由于 C# API 与 GDScript 存在差异,使用该 API 时请参考 C# 差异指南。例如has()在 C# 中更名为Contains,sort_custom()在 C# 中不受支持,Godot.Collections.Array的拼接也仅在 Godot 集合类型上可用。

实战选型建议与易错点清单

  1. 优先类型化:数据类型已知(含自定义类)时用Array[Type],能获得更快的迭代/修改速度与编译期检查;静态类型分析 会考虑类型化数组约束。
  2. 大批量同质数据用压缩数组:达到成千上万个元素、且类型匹配Packed*家族时,选择压缩数组换取内存与性能;需要map/filter等便捷方法时再转回普通数组。
  3. 副本用duplicate:涉及嵌套结构修改时明确选择浅拷贝(默认)或深拷贝(deep=true/duplicate_deep),并牢记深拷贝仍共享 Resource。
  4. 插入/删除是 O(n) 操作:push_front、insert、erase、remove_at、pop_front都会移动后续元素索引,大数组下应评估队列(Queue)或调整数据结构。
  5. 二分搜索前提是有序:bsearch/bsearch_custom只对已排序数组可靠,且sort()/sort_custom()不稳定、sort_custom的比较器必须返回一致结果。
  6. 遍历期间不改动长度:需要增删时先收集索引或改用for i in array.size()模式,避免不可预测行为。
  7. 区分类型敏感比较:find/has受 Variant.Type 影响,7与7.0不相等;布尔上下文只区分空与非空。

参考资料

  • Array 类参考(本文骨架源)
  • GDScript 基础:容器类型、类型化数组与压缩数组
  • GDScript 静态类型分析
  • C# 集合指南:Array 与 PackedArray 映射
  • C# 与 GDScript 的 API 差异
  • 压缩数组类参考:PackedByteArray、PackedInt32Array、PackedInt64Array、PackedFloat32Array、PackedFloat64Array、PackedStringArray、PackedVector2Array、PackedVector3Array、PackedVector4Array、PackedColorArray
  • 文档
  • 教程
  • 游戏开发

【免费下载链接】godot-docs

Godot Engine official documentation

项目地址:https://gitcode.com/GitHub_Trending/go/godot-docs
点击查看免费下载

相关推荐

上一篇:Splunk 威胁情报富化管道实战:从 Feed 接入到 IOC 生命周期治理
下一篇:PaddleOCR 基于 PaddleHub Serving 的服务化部署实战指南:从文本检测到 PP-Structure 与 KIE 一键上线

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询