GO语言基本语法
GO语言变量声明
-
var name type
var a int
-
批量声明
var( a int b string c []float32 d func()bool e struct { x int } )
-
简短格式
名字:=表达式
-定义变量,同时显式初始化
-不能提供数据类型
-只能用在函数内部
GO语言的基本数据类型:
- bool
- string
- int,int 8,int 16,int 32,int 64
- uint,uint 8,uint 16,uint 32,uint 64,uintptr
- byte//uint8的别名
- rune//int32的别名,代表一个unicode码
- complex64,comlpex128
GO语言变量的初始化
var name type=表达式 var a int=100
var name=表达式 vr a =100
name:=表达式 a:=100
匿名变量
_,_=表达式,表达式
GO语言变量的作用域
全局 局部 形参
string
-
使用“ ”定义字符串
var a="hello word"
- 拼接字符串
s1:=s2+s3 s1+=s2
Go 语言中也有类似于 StringBuilder 的机制来进行高效的字符串连接 hammer := "吃我一锤" sickle := "死吧" // 声明字节缓冲 var stringBuilder bytes.Buffer // 把字符串写入缓冲 stringBuilder.WriteString(hammer) stringBuilder.WriteString(sickle) // 将缓冲以字符串形式输出 fmt.Println(stringBuilder.String()) bytes.Buffer 是可以缓冲并可以往里面写入各种字节数组的。字符串也是一种字节数组,使用 WriteString() 方法进行写入。 将需要连接的字符串,通过调用 WriteString() 方法,写入 stringBuilder 中,然后再通过 stringBuilder.String() 方法将缓冲转换为字符串。
- 定义多行字符串
const str=`第一行 第二行 第三行 \r\n `
-
字符串长度
GO语言可以使用内建函数len(),可以获取切片、字符串、通道(channel)等的长度 tip1 := "genji is a ninja" fmt.Println(len(tip1)) tip2 := "忍者" fmt.Println(len(tip2)) 程序输出 16 6 len()函数的返回值时int,表示字符串的ASCLL字符的个数
Go 语言中 UTF-8 包提供的 RuneCountInString() 函数,统计 Uncode 字符数量 fmt.Println(utf8.RuneCountInString("忍者")) fmt.Println(utf8.RuneCountInString("龙忍出鞘,fight!")) 程序输出如下: 2 11
- ASCII 字符串长度使用 len() 函数。
- Unicode 字符串长度使用 utf8.RuneCountInString() 函数。
-
遍历字符串
遍历每一个ASCII字符 theme := "狙击 start" for i := 0; i < len(theme); i++ { fmt.Printf("ascii: %c %d\n", theme[i], theme[i]) } 程序输出: ascii: ? 231 ascii: 139 ascii: 153 ascii: ? 229 ascii: 135 ascii: ? 187 ascii: 32 ascii: s 115 ascii: t 116 ascii: a 97 ascii: r 114 ascii: t 116
按Unicode字符遍历字符串 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
- ASCII 字符串遍历直接使用下标。
- Unicode 字符串遍历用 for range。
-
字符串的截取
下面例子中使用 strings.Index() 函数在字符串中搜索另外一个子串,代码如下 tracer := "死神来了, 死神bye bye" comma := strings.Index(tracer, ", ") pos := strings.Index(tracer[comma:], "死神") fmt.Println(comma, pos, tracer[comma+pos:]) 程序输出: 12 3 死神bye bye
- strings.Index:正向搜索子字符串。
- strings.LastIndex:反向搜索子字符串。
- 搜索的起始位置可以通过切片偏移制作
-
修改字符串
Go 语言的字符串无法直接修改每一个字符元素,只能通过重新构造新的字符串并赋值给原来的字符串变量实现
angel := "Heros never die" angleBytes := []byte(angel) for i := 5; i <= 10; i++ { angleBytes[i] = \' \' } fmt.Println(string(angleBytes)) 程序输出如下: Heros die
感觉我们通过代码达成了修改字符串的过程,但真实的情况是:Go 语言中的字符串和其他高级语言(Java、C#)一样,默认是不可变的(immutable)。
字符串不可变有很多好处,如天生线程安全,大家使用的都是只读对象,无须加锁;再者,方便内存共享,而不必使用写时复制(Copy On Write)等技术;字符串 hash 值也只需要制作一份
- Go 语言的字符串是不可变的。
- 修改字符串时,可以将字符串转换为 []byte 进行修改。
- []byte 和 string 可以通过强制类型转换互转。
-
fmt.Sprintf
fmt.Sprintf(格式化样式, 参数列表…)
fmt.Println(title) pi := 3.14159 // 按数值本身的格式输出 variant := fmt.Sprintf("%v %v %v", "月球基地", pi, true) "月球基地" 3.14159 true
动 词 功 能 %v 按值的本来值输出 %+v 在 %v 基础上,对结构体字段名和值进行展开 %#v 输出 Go 语言语法格式的值 %T 输出 Go 语言语法格式的类型和值 %% 输出 % 本体 %b 整型以二进制方式显示 %o 整型以八进制方式显示 %d 整型以十进制方式显示 %x 整型以十六进制方式显示 %X 整型以十六进制、字母大写方式显示 %U Unicode 字符 %f 浮点数 %p 指针,十六进制方式显示 -
Base64 编码
Base64 编码是常见的对 8 比特字节码的编码方式之一。Base64 可以使用 64 个可打印字符来表示二进制数据,电子邮件就是使用这种编码。
Go 语言的标准库自带了 Base64 编码算法,通过几行代码就可以对数据进行编码,示例代码如下。
package main import ( "encoding/base64" "fmt" ) func main() { // 需要处理的字符串 message := "Away from keyboard. https://golang.org/" // 编码消息 encodedMessage := base64.StdEncoding.EncodeToString([]byte (message)) // 输出编码完成的消息 fmt.Println(encodedMessage) // 解码消息 data, err := base64.StdEncoding.DecodeString(encodedMessage) // 出错处理 if err != nil { fmt.Println(err) } else { // 打印解码完成的数据 fmt.Println(string(data)) } }
GO语言字符串类型
Go语言的字符有以下两种:
-
一种是 uint8 类型,或者叫 byte 型,代表了 ASCII 码的一个字符。
-
另一种是 rune 类型,代表一个 UTF-8 字符,当需要处理中文、日文或者其他复合字符时,则需要用到 rune 类型。rune 类型等价于 int32 类型。
在 ASCII 码表中,A 的值是 65,使用 16 进制表示则为 41,所以下面的写法是等效的:
var ch byte = 65 或 var ch byte = \'\x41\' //(\x 总是紧跟着长度为 2 的 16 进制数)
另外一种可能的写法是
\
后面紧跟着长度为 3 的八进制数,例如 \377。
Go语言同样支持 Unicode(UTF-8),因此字符同样称为 Unicode 代码点或者 runes,并在内存中使用 int 来表示。在文档中,一般使用格式 U+hhhh 来表示,其中 h 表示一个 16 进制数。
格式化说明符%c
用于表示字符,当和字符配合使用时,%v
或%d
会输出用于表示该字符的整数,%U
输出格式为 U+hhhh 的字符串。
Unicode 包中内置了一些用于测试字符的函数,这些函数的返回值都是一个布尔值,如下所示(其中 ch 代表字符):
- 判断是否为字母:unicode.IsLetter(ch)
- 判断是否为数字:unicode.IsDigit(ch)
- 判断是否为空白符号:unicode.IsSpace(ch)
GO语言数据类型转化
valueOfTypeB = typeB(valueOfTypeA)
类型转换只能在定义正确的情况下转换成功,例如从一个取值范围较小的类型转换到一个取值范围较大的类型(将 int16 转换为 int32)。当从一个取值范围较大的类型转换到取值范围较小的类型时(将 int32 转换为 int16 或将 float32 转换为 int),会发生精度丢失(截断)的情况。
只有相同底层类型的变量之间可以进行相互转换(如将 int16 类型转换成 int32 类型),不同底层类型的变量相互转换时会引发编译错误(如将 bool 类型转换为 int 类型):
GO语言指针
指针(pointer)在Go语言中可以被拆分为两个核心概念:
- 类型指针,允许对这个指针类型的数据进行修改,传递数据可以直接使用指针,而无须拷贝数据,类型指针不能进行偏移和运算。
- 切片,由指向起始元素的原始指针、元素数量和容量组成。
GO语言变量逃逸
使用 go run 运行程序时,-gcflags 参数是编译参数。其中 -m 表示进行内存分配分析,-l 表示避免程序内联,也就是避免进行程序优化
编译器觉得变量应该分配在堆和栈上的原则是:
- 变量是否被取地址;
- 变量是否发生逃逸。
请发表评论