GO:微软的 VC 编译器会将未初始化的栈空间以 16 进制的 0xCC 填充,而未初始化的堆空间使用 0xCD 填充,而 0xCCCC 和 0xCDCD 在中文的 GB2312 编码中刚好对应“烫”和“屯”字
目录
基本类型
string int、int8、int16、int32、int64 uint、uint8、uint16、uint32、uint64、uintptr byte // uint8 的别名 rune // int32 的别名 代表一个 Unicode 码 float32、float64 complex64、complex128 当一个变量被声明之后,系统自动赋予它该类型的零值:int 为 0,float 为 0.0,bool 为 false,string 为空字符串,指针为 nil 等。所有的内存在 Go 中都是经过初始化的,
和 var 形式声明语句一样,简短变量声明语句也可以用来声明和初始化一组变量:
i, j := 0, 1
变量初始化的标准格式
var 变量名 类型 = 表达式:var hp int = 100 省略后:var hp = 100
注意:在多个短变量声明和赋值中,至少有一个新声明的变量出现在左值中,即便其他变量名可能是重复声明的,编译器也不会报错,代码如下:
conn, err := net.Dial("tcp", "127.0.0.1:8080")
conn2, err := net.Dial("tcp", "127.0.0.1:8080")
字符类型:byte和rune
Go语言的字符有以下两种:
- 一种是 uint8 类型,或者叫 byte 型,代表了 ASCII 码的一个字符。
- 另一种是 rune 类型,代表一个 UTF-8 字符,当需要处理中文、日文或者其他复合字符时,则需要用到 rune 类型。rune 类型等价于 int32 类型。
——byte 类型是 uint8 的别名,对于只占用 1 个字节的传统 ASCII 编码的字符来说,完全没有问题,例如 var ch byte = 'A',字符使用单引号括起来。在 ASCII 码表中,A 的值是 65,使用 16 进制表示则为 41,所以下面的写法是等效的:
var ch byte = 'A'
var ch byte = 65
var ch byte = '\x41' //(\x 总是紧跟着长度为 2 的 16 进制数)
——Go语言同样支持 Unicode(UTF-8),因此字符同样称为 Unicode 代码点或者 runes,并在内存中使用 int 来表示。在文档中,一般使用格式 U+hhhh 来表示,其中 h 表示一个 16 进制数。在书写 Unicode 字符时,需要在 16 进制数之前加上前缀\u
或者\U
。因为 Unicode 至少占用 2 个字节,所以我们使用 int16 或者 int 类型来表示。如果需要使用到 4 字节,则使用\u
前缀,如果需要使用到 8 个字节,则使用\U
前缀。
var ch int = '\u0041'
var ch2 int = '\u03B2'
var ch3 int = '\U00101234'
fmt.Printf("%d - %d - %d\n", ch, ch2, ch3) // integer
// 输出: 65 - 946 - 1053236 [十六进制到十进制(%d)]
fmt.Printf("%c - %c - %c\n", ch, ch2, ch3) // character
// 输出: A - β - r [字符(%c)]
fmt.Printf("%X - %X - %X\n", ch, ch2, ch3) // UTF-8 bytes
// 输出: 41 - 3B2 - 101234 [十六进制(%X)]
fmt.Printf("%U - %U - %U", ch, ch2, ch3) // UTF-8 code point
// 输出: U+0041 - U+03B2 - U+101234 [U+X(%U)]
UTF-8 和 Unicode 有何区别?
Unicode 与 ASCII 类似,都是一种字符集。
字符集为每个字符分配一个唯一的 ID,我们使用到的所有字符在 Unicode 字符集中都有一个唯一的 ID,例如上面例子中的 a 在 Unicode 与 ASCII 中的编码都是 97。汉字“你”在 Unicode 中的编码为 20320,在不同国家的字符集中,字符所对应的 ID 也会不同。而无论任何情况下,Unicode 中的字符的 ID 都是不会变化的。
UTF-8 是编码规则,将 Unicode 中字符的 ID 以某种方式进行编码,UTF-8 的是一种变长编码规则,从 1 到 4 个字节不等。编码规则如下:
- 0xxxxxx 表示文字符号 0~127,兼容 ASCII 字符集。
- 从 128 到 0x10ffff 表示其他字符。
根据这个规则,拉丁文语系的字符编码一般情况下每个字符占用一个字节,而中文每个字符占用 3 个字节。
广义的 Unicode 指的是一个标准,它定义了字符集及编码规则,即 Unicode 字符集和 UTF-8、UTF-16 编码等。
GO指针
1.结构体变量和结构体指针均可以用下标访问成员(Type.pam),Go会自动识别其类型
func (p *Ptr_test)modify_number_1() //调用时会影响变量本身状态
func (p Ptr_test)modify_number_2() //调用时不会影响变量本身状态
2.函数传参时均为值传递,即函数内的参数为传参的拷贝
func (p *Ptr_test)modify_ptr(ph *Ptr_test){
p = ph //不会改变p所指对象的值
*p = *ph //会改变P所指对象的值
}
3.make和new的区别:make用来创建切片(可变数组),map和通道(队列),指向一个已经被初始化的内存的引用,可以直接使用;但是new创建的是一个指向对应类型的指针,指针所指向的内存需要初始化之后才能使用。(make是引用,new是指针,如果需要用make创建指针,直接把类型设为指针即可)
——make
slice := make([]Ptr_test, 1) // 此时可访问slice[0],其成员全部为初始值,后续用append会从1开始
slice = append(slice,pam_1)
hash := make(map[int]Ptr_test, 10)
hash["kaka"] = pam_1
ch := make(chan Ptr_test, 5) // 容量为5(必须指定), 超过5溢出,长度为当前通道实际存放的变量大小
ch2 := make(chan interface{}, 5) //指定任意类型
ch <- pam1
ch <- pam2 // 放入通道
pam3 := <- ch // ch 先进厦先出原则,此时pam3为pam1的拷贝
<- ch // 执行后ch为空,其长度变为0
——new: 很少情况下需要使用new,除非你真的喜欢这个单词。
// 切片
slice_a := new([]Ptr_test) // 初始化之后才可用
*slice_a = append(*slice_a, a_pam1) //初始化, (*slice_a)[0].name 访问成员
//哈希表
hash_a := new(map[string]Ptr_test)
//map需要初始化之后才能使用
*hash_a = map[string]Ptr_test{} //第1种
*hash_a = make(map[string]Ptr_test, 0) //第2种
(*hash_a)["kaka"] = a_pam1
fmt.Printf("hash: %s ",(*hash_a)["kaka"].name)
字符串
1-字符串长度
- ASCII 字符串长度使用 len() 函数,表示字符串的 ASCII 字符个数或字节长度。
- Unicode 字符串长度使用 utf8.RuneCountInString() 函数。
str_name := "卡卡kaka"
n1 := len(str_name) //长度为 11,go采用UTF-8编码,一个中文3个字节。
n2 := utf8.RuneCountInString(str_name) // 长度为6
2- 字符串遍历
- ASCII 字符串遍历直接使用下标。
- Unicode 字符串遍历用 for range,逐字符遍历会出现
theme := "狙击 start"
for _, s := range theme {
fmt.Printf("Unicode: %c %d\n", s, s)
}
Unicode: 狙 29401
Unicode: 击 20987
Unicode: 32
Unicode: s 115
Unicode: t 116
Unicode: a 97
Unicode: r 114
Unicode: t 116
3- 字符串截取
tracer := "死神来了, 死神bye bye"
comma := strings.Index(tracer, ", ")
pos := strings.Index(tracer[comma:], "死神")
fmt.Println(comma, pos, tracer[comma+pos:])
// strings.Index:正向搜索子字符串。
// strings.LastIndex:反向搜索子字符串。
// 搜索的起始位置可以通过切片偏移制作。
—— comma 逗号的位置是 12,而 pos 是相对位置,值为 3。我们为了获得第二个“死神”的位置,也就是逗号后面的字符串,就必须让 comma 加上 pos 的相对偏移,计算出 15 的偏移,然后再通过切片 tracer[comma+pos:] 计算出最终的子串,获得最终的结果:“死神bye bye”。
4-修改字符串
angel := "Heros never die"
angleBytes := []byte(angel) // 在第 3 行中,将字符串转为字符串数组。byte = uint8
for i := 5; i <= 10; i++ {
angleBytes[i] = ' ' // 将 never 单词替换为空格。
}
fmt.Println(string(angleBytes)) // Heros die
- Go 语言的字符串是不可变的。
- 修改字符串时,可以将字符串转换为 []byte 进行修改。
- []byte 和 string 可以通过强制类型转换互转。
5-字符串拼接
hammer := "kaka"
sickle := "molaiwei"
// 声明字节缓冲
var stringBuilder bytes.Buffer
// 把字符串写入缓冲
stringBuilder.WriteString(hammer)
stringBuilder.WriteString(sickle)
// 将缓冲以字符串形式输出
fmt.Println(stringBuilder.String())
6-格式化输出: fmt.Printf()
动 词 | 功 能 |
---|---|
%v | 按值的本来值输出 |
%+v | 在 %v 基础上,对结构体字段名和值进行展开 |
%#v | 输出 Go 语言语法格式的值 |
%T | 输出 Go 语言语法格式的类型和值 |
%% | 输出 % 本体 |
%b | 整型以二进制方式显示 |
%o | 整型以八进制方式显示 |
%d | 整型以十进制方式显示 |
%x | 整型以十六进制方式显示 |
%X | 整型以十六进制、字母大写方式显示 |
%U | Unicode 字符 |
%f | 浮点数 |
%p | 指针,十六进制方式显示 |