类型
-
类型转化。与其他主要编程语⾔言的差异
- Go 语言不允许隐式类型转换
- 别名和原有类型也不能进⾏隐式类型转换
type MyInt int64 func TestType(t *testing.T) { var a int = 1 var b int64 = 2 b = int64(a) var c MyInt c = MyInt(b) t.Log(a, b, c) // 1 1 1 } -
类型的预定义值
- math.MaxInt64: 9223372036854775807
- math.MaxFloat64: 1.7976931348623157e+308
- math.MaxUint32: 4294967295
指针类型,与其他主要编程语⾔言的差异
- 不支持指针运算
func TestPoint(t *testing.T) {
a := 1
aPtr := &a
t.Logf("%T %T", a, aPtr) // int *int
t.Log(a, aPtr) // 1 0xc0000a40d0
}
func TestPoint(t *testing.T) {
a := 1
aPtr := &a
aPtr = aPtr + 1
t.Log(a, aPtr) // cannot convert 1 (untyped int constant) to *int
}
- string 是值类型,其默认的初始化值为空字符串,⽽不是 nil
func TestPoint(t *testing.T) {
var s string
t.Log(s == "") // true
}
整型
- 整型溢出问题最容易发生在循环语句的结束条件判断中,因为这也是经常使用整型变量的地方。无论无符号整型,还是有符号整型都存在溢出的问题,所以我们要十分小心地选择参与循环语句结束判断的整型变量类型,以及与之比较的边界值。
- 我们可以通过 type 关键字基于原生数值类型来声明一个新类型。通过 Go 提供的类型别名(Type Alias)语法来自定义数值类型。
字符串类型
-
string 类型其实是一个“描述符”,它本身并不真正存储字符串数据,而仅是由一个指向底层存储的指针和字符串的长度字段组成的。因为字符串类型中包含了字符串长度信息,当我们用 len 函数获取字符串长度时,len 函数只要简单地将这个信息提取出来就可以了。
-
Go 原生支持 string 的优点:
- string 类型的数据是不可变的,提高了字符串的并发安全性和存储利用率。
- 没有结尾’\0’,而且获取长度的时间复杂度是常数时间,消除了获取字符串长度的开销。
- 原生支持“所见即所得”的原始字符串,大大降低构造多行字符串时的心智负担。
- 对非 ASCII 字符提供原生支持,消除了源码在不同环境下显示乱码的可能。Unicode 字符是以 UTF-8 编码格式存储在内存当中的。
-
直接将 string 类型通过函数 / 方法参数传入也不会带来太多的开销。
-
Go 字符串类型的常见操作
- for 迭代与 for range 迭代两种形式的迭代对字符串进行操作得到的结果是不同的
- for 迭代对字符串进行的操作是一种字节视角的迭代
- for range 迭代,我们每轮迭代得到的是字符串中 Unicode 字符的码点值,以及该字符在字符串中的偏移值。
- Go 采用字典序的比较策略,分别从每个字符串的起始处,开始逐个字节地对两个字符串类型变量进行比较
-
与其他主要编程语⾔的差异
- string 是数据类型,不是引⽤或指针类型
- string 是只读的 byte slice,len 函数可以它所包含的 byte 数
- string 的 byte 数组可以存放任何数据
-
Unicode VS UTF8
- Unicode 是⼀种字符集(code point)
- UTF8 是 unicode 的存储实现 (转换为字节序列的规则)
func TestString(t *testing.T) { s := "\xE4\xB8\xAD" t.Log(s, len(s)) // 中 3 s = "中" t.Logf("中 UTF-8 %x", s) // 中 UTF-8 e4b8ad t.Log(s, len(s)) // 中 3 (是byte数) c := []rune(s) t.Log(c, len(c)) // [20013] 1 t.Logf("中 unicode %x", c[0]) //中 unicode 4e2d } -
遍历
func TestStringFunc(t *testing.T) { s := "A,B,C" parts := strings.Split(s, ",") for _, part := range parts { t.Log(part) } s1 := strings.Join(parts, "-") t.Log(s1) // A-B-C } -
转化
func TestStringConvert(t *testing.T) { i := strconv.Itoa(10) t.Logf("type: %T", i) // type: string s := "10" if v, err := strconv.Atoi(s); err == nil { t.Log(10 + v) // 20 } }