【GO】变量类型及定义

GO:微软的 VC 编译器会将未初始化的栈空间以 16 进制的 0xCC 填充,而未初始化的堆空间使用 0xCD 填充,而 0xCCCC 和 0xCDCD 在中文的 GB2312 编码中刚好对应“烫”和“屯”字

目录

基本类型

GO指针

字符串长度


基本类型

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()

表1:字符串格式化时常用动词及功能
动  词 功  能
%v 按值的本来值输出
%+v 在 %v 基础上,对结构体字段名和值进行展开
%#v 输出 Go 语言语法格式的值
%T 输出 Go 语言语法格式的类型和值
%% 输出 % 本体
%b 整型以二进制方式显示
%o 整型以八进制方式显示
%d 整型以十进制方式显示
%x 整型以十六进制方式显示
%X 整型以十六进制、字母大写方式显示
%U Unicode 字符
%f 浮点数
%p 指针,十六进制方式显示

 

上一篇:Jmeter 查看结果树显示unicode转中文


下一篇:2-Windows程序设计第五版 -Unicode 和 宽字符