Go具有内置的字符串类型,并且内置比较运算符,如==,!=和<(和Java一样)。 像Java一样,字符串是不可变的,所以一旦创建便不能更改,不过可以通过将其他字符串与内置运算符 + 中的其他串连接起来来创建新字符串。 例如:
str1:=“foo” str2:= str1 +“bar”GO语言源代码总是UTF-8编码,字符串文本可能包含非ASCII utf-8代码点。 GO调用Unicode代码点“runes(符文)”。
虽然内置的len()函数返回字节数,而字符串的内置运算符[]运行在字节上,但是有一个utf8包用于处理字符串作为符号(Unicode代码点)。 例如:
str:=“foo” l:= utf8.RuneCountInString(str)而基于范围的for循环在runes中处理,而不是字节:
str:=“foo” for _,r:= range str { fmt.Println(“rune:%q”,r) }c++ 仍没有标准等效项。
Slices(切片)GO语言的Slices(切片)与 c 中动态分配的数组类似, 尽管它们实际上是底层数组的视图, 而两个切片可以是同一底层数组的不同部分的视图。他他们感觉有点像C ++ 17或GSL :: span中的std :: string_view,但它们可以轻松调整大小,如C ++ 17中的std :: vector或Java中的ArrayList。
我们可以声明一个像这样的范围, 并追加到它:
a := []int{5, 4, 3, 2, 1} // A slice a = append(a, 0)数组(大小固定,不像切片)具有非常相似的语法:
a := [...]int{5, 4, 3, 2, 1} // An array. b := [5]int{5, 4, 3, 2, 1} // Another array.通过指针将数组传递给函数使用时必须注意,否则就会导致按值赋值。
与C ++中的std :: array或std :: vector不同,切片不是(深度)可比较或可复制���,这感觉相当不方便。
如果内置的append()函数需要比现有容量多(可能超过当前长度),则可以分配更大的底层数组。 所以你应该始终如此分配append()的结果:
a = append(a, 123)我认为你不能将指针指向切片中的元素。 如果可以的话,垃圾收集系统需要保留以前的底层数组,直到你停止使用该指针。
与C或C ++数组不同,不同于使用std :: vector的operator [],尝试访问切片的无效索引将导致紧急(有效地崩溃),而不仅仅是未定义的行为。 我更喜欢这个,虽然我想像是边界检查有一些小的性能成本。
Maps(映射)Go有一个内置的 map 类型。这大致相当于C ++的std :: map(平衡二叉树)或std :: unordered_map(哈希表)。GO的maps显然是哈希表,但是我不知道它们是单独链接的哈希表(如std::unordered_map)还是开放寻址哈希表(不幸的是,标准C ++中没有什么)。
显然,哈希表中的 keys 必须是hashable 和 comparable。这本书提到了可比性,但是很少有事情是可比的,他们都很容易hashable。只有基本类型(int,float64,string等,但不是slice)或数据结构是可比较的,所以可以用它们作为一个关键。可以通过使用(或制作)您的值的哈希值的基本类型(如int或字符串)来解决此问题。我喜欢C ++需要一个std :: hash <>专业化,尽管我希望写一个更容易。
与C ++不同,您不能保留指向地图中的元素的指针,因此更改值的一部分意味着将整个值复制回地图,大概用另一个查找。显然,当地图必须增长时,完全避免无效指针的问题。 C ++可以让您承担风险,指定何时可能无效。
Go Maps显然是一个比C更大的优势,否则您必须使用一些第三方数据结构或编写自己的数据,通常只有很少的类型安全。
看起来像下面这样:
m := make(map[int]string) m[3] = "three" m[4] = "four" Multiple return values(多个返回值)