1 标识符
标识符的英文是identifier,通俗讲,就是给变量、常量、函数、方法、结构体、数组、切片、接口起名字。
标识符的组成:
1.标识符由数字、字母和下划线(_)组成。
2.只能以字母和下划线(_)开头。 如:abc123 _sysVar
3.标识符区分大小写。 如:name、Name、NAME
func main() {
// 正确的标识符
var name string
var age int
var _sys int
// 错误的标识符
var 1name string
var &age int
var !email
}
2 关键字
Go语言提供了25个关键字,如下所示:
| break | default | func | interface | select |
|---|---|---|---|---|
| case | defer | go | map | struct |
| chan | else | goto | package | switch |
| const | fallthrough | if | range | type |
| continue | for | import | return | var |
除了以上关键字,Go语言还有36个预定义标识符,其中包含了基本类型的名称和一些基本的内置函数,见下表:
| append | bool | byte | cap | close | cpmplex | complex64 | complex128 | uint16 |
|---|---|---|---|---|---|---|---|---|
| copy | false | float32 | float64 | imag | int | int8 | int16 | uint32 |
| int32 | int64 | iota | len | make | new | nil | panic | uint64 |
| println | real | recover | string | true | uint | uint8 | uintptr |
3 命名规则
3.1 Go语言区分大小写
命名规则涉及变量、常量、全局函数、结构、接口、方法等的命名。
Go语言从语法层面进行了以下限定:任何需要对外暴露的名字必须以大写字母开头,不需要对外暴露的则应该以小写字母开头。
当命名(常量、变量、类型、函数名、结构字段等)以一个大写字母开头,如:GetUserName,那么使用这种形式的标识符的对象就可以被外部包的代码所使用(客户端程序需要先导入这个包),这被称为导出(像面向对象语言中的 public); 命名如果以小写字母开头,则对包外是不可见的,但是他们在整个包的内部是可见并且可用的(像面向对象语言中的 private )。
3.2 包名称
保持package的名字和目录保持一致,尽量采取简短、有意义的包名,不和标准库冲突。包名应该为小写单词,不要使用下划线或者混合大小写。
package dao
package service
3.3 文件命名
尽量采取简短、有意义的文件名,应该为小写单词,使用下划线分隔各个单词。
customer_dao.go
3.4 结构体命名
采用驼峰命名法,首字母根据访问控制大写或者小写
struct 申明和初始化格式采用多行,例如下面:
type CustomerOrder struct {
Name string
Address string
}
order := CustomerOrder{"tom", "北京海淀"}
3.5 接口命名
命名规则基本和上面的结构体类型
单个函数的结构名以 “er” 作为后缀,例如 Reader , Writer 。
type Reader interface {
Read(p []byte) (n int, err error)
}
3.6 变量命名
和结构体类似,变量名称一般遵循驼峰法,首字母根据访问控制原则大写或者小写,但遇到特有名词时,需要遵循以下规则:
如果变量为私有,且特有名词为首个单词,则使用小写,如 appService。
若变量类型为 bool 类型,则名称应以 Has、Is、Can 或 Allow 开头。
var isExist bool
var hasConflict bool
var canManage bool
var allowGitHook bool
3.7 常量命名
常量均需使用全部大写字母组成,并使用下划线分词
const APP_URL = "https://www.duoke360.com"
如果是枚举类型的常量,需要先创建相应类型:
type Scheme string
const (
HTTP Scheme = "http"
HTTPS Scheme = "https"
)
3.8 错误处理
错误处理的原则是不能丢弃任何有返回err的调用,不要使用 _ 丢弃,必须全部处理。
接收到错误,要么返回err,或者使用log记录下来尽早return:一旦有错误发生,马上返回,尽量不要使用panic,除非你知道你在做什么,错误描述如果是英文必须为小写,不需要标点结尾,采用独立的错误流进行处理
// 错误写法
if err != nil {
// 错误处理
} else {
// 正常代码
}
// 正确写法
if err != nil {
// 错误处理
return // 或者继续
}
// 正常代码
3.9 单元测试
单元测试文件名命名规范为 example_test.go, 测试用例的函数名称必须以 Test 开头,例如:TestExample 每个重要的函数都要首先编写测试用例,测试用例和正规代码一起提交方便进行回归测试 。
4 Golang变量
变量是计算机语言中能储存计算结果或能表示值的抽象概念。
不同的变量保存的数据类型可能会不一样。
4.1 声明变量
Go语言中的变量需要声明后才能使用,同一作用域内不支持重复声明。 并且Go语言的变量声明后必须使用。
1.声明变量的语法
var identifier type
var:声明变量关键字
identifier:变量名称
type:变量类型
func main() {
var name string
var age int
var b bool
}
4.2 批量声明变量
使用一个var关键字,把一些变量写在一个括号()里
func main() {
// 声明变量
/* var name string
var age int
var b bool */
// 批量声明变量
var (
name string
age int
b bool
)
name = "Tom"
age = 20
b = true
// name.Printf!、age.Printf!、m.Printf!......
fmt.Printf("name: %v\n", name)
fmt.Printf("age: %v\n", age)
fmt.Printf("b: %v\n", b)
}
4.3 变量初始化
Go语言在声明变量的时候,会自动对变量对应的内存区域进行初始化操作。每个变量会被初始化成其类型的默认值,例如: 整型和浮点型变量的默认值为0。 字符串变量的默认值为空字符串“”。 布尔型变量默认为false。 切片、函数、指针变量的默认为nil。
1.变量初始化语法:var 变量名 类型 = 表达式
func main() {
// 初始化---赋初值
var name string = "小罗"
var site string = "https://linuxtech.top"
var age int = 27
}
2.类型推导:声明变量时,可根据初始化值进行类型推导,从而省略类型。
func main() {
// 类型推导
var name = "小罗"
var site = "https://linuxtech.top"
var age = 30
}
3.初始化多个变量:可以一次初始化多个变量,中间用逗号分隔。
func main() {
// 变量的批量初始化
var name, site, age = "小罗", "https://linuxtech.top", 27
}
4.4 短变量声明
在函数内部,可以使用 :=运算符对变量进行声明和初始化。
func main() {
// 短变量声明 :=
name := "小罗"
site := "https://linuxtech.top"
age := 27
}
注意:这种方法只适合在函数内部,函数外面不能使用。
4.5 匿名变量
如果接收到多个变量,有一些变量使用不到,可以使用下划线_表示变量名称,这种变量叫做匿名变量。例如:
/* func getData() (name string, site string, age int) {
return "小罗", "https://linuxtech.top", 27
} */
func getData() (string, string, int) {
return "小罗", "https://linuxtech.top", 27
}
func main() {
// 使用不到的变量可以用_表示变量名称
name, _, age := getData()
fmt.Printf("name: %v\n", name)
fmt.Printf("age: %v\n", age)
}
5 Golang常量
常量是程序编译阶段就确定下来的值,而程序在运行时则无法改变该值。在Go程序中,常量可以是数值类型(整型、浮点型和复数类型)、布尔类型、字符串类型等。
5.1 定义常量
定义一个常量使用const关键字,语法格式如下:
const constantName [type]= value
const:定义常量关键字
constantName:常量名称
type:常量类型
value:常量的值
func main() {
// 声明常量
const PI float64 = 3.14
const PI2 = 3.1415 // 可省略类型
const (
width = 100
height = 200
)
const a, b, c = "小罗", 27, "https://linuxtech.top/"
}
5.2 声明多个常量
const同时声明多个常量时,如果省略了值则表示和上面一行的值相同
func main() {
const (
m = 908
n
p
)
fmt.Printf("m: %v\n", m)
......
}
// 运行结果 m: 908 n: 908 p: 908
5.3 iota
iota 比较特殊,可以被认为是一个可被编译器修改的常量,它默认开始值是0,每调用一次加1。遇到 const 关键字时被重置为 0。
func main() {
const (
a1 = iota
a2 = iota
a3 = iota
)
fmt.Printf("a1: %v\n", a1)
......
}
// 运行结果 a1: 0 a2: 1 a3: 2
1.使用_跳过某些值
func main() {
const (
a1 = iota
_
a2 = iota
)
fmt.Printf("a1: %v\\n", a1)
......
}
// 运行结果 a1: 0 a2: 2
2.iota声明中间插队
func main() {
const (
a1 = iota
a2 = 567
a3 = iota
)
fmt.Printf("a1: %v\\n", a1)
......
}
// 运行结果 a1: 0 a2: 567 a3: 2
6 数据类型
在 Go 编程语言中,数据类型用于声明函数和变量。
数据类型的出现是为了把数据分成所需内存大小不同的数据,编程需要用大数据的时候才需要申请大内存,就可以充分利用内存。
Go 语言按类别有以下几种数据类型:
| 数据类型 | 描述 |
|---|---|
| 数字类型 | 整型–int、浮点型–float32、float64,Go语言支持整型和浮点型数字,并且支持复数,其中位的运算采用补码。 |
| 布尔型 | 布尔型的值只可以是常量 true 或者 false。 |
| 字符串 | 字符串是一串固定长度的字符连接起来的字符序列。 Go的字符串是由单个字节连接起来的。 Go语言字符串的字节使用 UTF-8 编码标识 Unicode 文本。 |
| 派生类型 | 指针、数组、结构化、Channel、函数、切片、接口、Map |
func fun() {
}
func main() {
age := 29
b := true
var name string = "小罗"
// 数字、布尔、字符串
// 格式化输出 %T代表类型 \n代表换行 快捷键ff===>fmt.Printf("", var)
fmt.Printf("%T\n", age)
......
// 指针类型
a := 567
p := &a // &a表示取a的地址
// 数组类型
m := [2]int{23, 56} // 长度为2的数组
// 切片类型
n := []int{23, 56, 890} // int类型的切片
// 函数类型
fmt.Printf("%T\n", fun)
}
6.1 数字类型
Go 语言支持整型和浮点型数字,并且原生支持复数,其中位的运算采用补码。
Go 也有基于架构的类型,例如:int、uint 和 uintptr。
类型的长度是根据运行程序所在的操作系统类型所决定的:
int 和 uint 在 32 位操作系统上,均使用 32 位(4 个字节),在 64 位操作系统上使用 64 位(8 个字节)。
uintptr 的长度被设定为足够存放一个指针即可。
Go 语言中没有 float 类型。
Go语言中只有 float32 和 float64,没有double类型。
与操作系统架构无关的类型都有固定的大小,并在类型的名称中就可以看出来:
int 型是计算最快的一种类型。
整型的零值为 0,浮点型的零值为 0.0。
| 数据类型 | 描述 |
|---|---|
| uint8 | 无符号 8 位整型 (0 到 255) |
| uint16 | 无符号 16 位整型 (0 到 65535) |
| uint32 | 无符号 32 位整型 (0 到 4294967295) |
| uint64 | 无符号 64 位整型 (0 到 18446744073709551615) |
| int8 | 有符号 8 位整型 (-128 到 127) |
| int16 | 有符号 16 位整型 (-32768 到 32767) |
| int32 | 有符号 32 位整型 (-2147483648 到 2147483647) |
| int64 | 有符号 64 位整型 (-9223372036854775808 到 9223372036854775807) |
各个数字类型的长度和取值范围如下:
package main
// 按住ctrl键,可以打开相关模块的外部链接
import (
"fmt"
"math"
"unsafe"
)
func main() {
var i8 int8
var i16 int16
var i32 int32
var i64 int64
var ui8 uint8
var ui16 uint16
var ui32 uint32
var ui64 uint64
fmt.Printf("%T %dB %v~%v\n", i8, unsafe.Sizeof(i8), math.MinInt8, math.MaxInt8)
fmt.Printf("%T %dB %v~%v\n", i16, unsafe.Sizeof(i16), math.MinInt16, math.MaxInt16)
fmt.Printf("%T %dB %v~%v\n", i32, unsafe.Sizeof(i32), math.MinInt32, math.MaxInt32)
fmt.Printf("%T %dB %v~%v\n", i64, unsafe.Sizeof(i64), math.MinInt64, math.MaxInt64)
fmt.Printf("%T %dB %v~%v\n", ui8, unsafe.Sizeof(ui8), 0, math.MaxUint8)
fmt.Printf("%T %dB %v~%v\n", ui16, unsafe.Sizeof(ui16), 0, math.MaxUint16)
fmt.Printf("%T %dB %v~%v\n", ui32, unsafe.Sizeof(ui32), 0, math.MaxUint32)
fmt.Printf("%T %dB %v~%v\n", ui64, unsafe.Sizeof(ui64), 0, uint64(math.MaxUint64))
var f32 float32
var f64 float64
fmt.Printf("%T %dB %v~%v\n", f32, unsafe.Sizeof(f32), -math.MaxFloat32, math.MaxFloat32)
fmt.Printf("%T %dB %v~%v\n", f64, unsafe.Sizeof(f64), -math.MaxFloat64, math.MaxFloat64)
var ui uint
ui = uint(math.MaxUint64) // 再+1会导致overflows错误
fmt.Printf("%T %dB %v~%v\n", ui, unsafe.Sizeof(ui), 0, ui)
var imax, imin int
imax = int(math.MaxInt64) // 再+1会导致overflows错误
imin = int(math.MinInt64) // 再-1会导致overflows错误
fmt.Printf("%T %dB %v~%v\n", imax, unsafe.Sizeof(imax), imin, imax)
}
二进制、八进制、十六进制浮点数的格式定义数字:
func main() {
// 十进制
var a int = 10
fmt.Printf("%d \n", a)
fmt.Printf("%b \n", a) // 占位符%b表示二进制
// 八进制 以0开头
var b int = 077
fmt.Printf("%o \n", b)
// 十六进制 以0x开头
var c int = 0xff
fmt.Printf("%x \n", c)
fmt.Printf("%X \n", c)
}
// 运行结果 10 1010 77 ff FF
6.2 浮点型
Go语言支持两种浮点型数:float32和float64,这两种浮点型数据格式遵循IEEE 754标准。
float32 的浮点数的最大范围约为 3.4e38,可以使用常量定义:math.MaxFloat32。
float64 的浮点数的最大范围约为 1.8e308,可以使用一个常量定义:math.MaxFloat64。
| 数据类型 | 描述 |
|---|---|
| float32 | IEEE-754 32位浮点型数 |
| float64 | IEEE-754 64位浮点型数 |
| complex64 | 32 位实数和虚数 |
| complex128 | 64 位实数和虚数 |
打印浮点数时,可以使用fmt包配合动词%f,代码如下:
func main() {
// 浮点类型
fmt.Printf("%f\n", math.Pi)
fmt.Printf("%.2f\n", math.Pi) // .2f表示两位小数
}
// 运行结果 3.141593 3.14
6.3 复数
复数有实部和虚部,complex64的实部和虚部为32位,complex128的实部和虚部为64位。
func main() {
// 复数
var c1 complex64
c1 = 1 + 6i
var c2 complex128
c2 = 3 + 8i
fmt.Println(c1)
fmt.Println(c2)
}
// 运行结果 (1+6i)(3+8i)
6.4 布尔类型
Go语言中的布尔类型有两个常量值:true和false。布尔类型经常用在条件判断语句、循环语句,也可用在逻辑表达式中。
func main() {
var b1 bool = true
var b2 bool = false
var b3 = true
var b4 = false
b5 := true
b6 := false
fmt.Printf("b1: %v\n", b1)
......
}
1.用在条件判断中
func main() {
// 1.用在条件判断中
age := 16
r := age >= 18
if r {
fmt.Println("你已经成年了!")
} else {
fmt.Println("你还未成年!")
}
}
// 运行结果: 你还未成年!
2.用在循环语句中
func main() {
// 2.用在循环语句中
count := 10
for i := 0; i < count; i++ {
fmt.Printf("i: %v\n", i) // 快捷键---i.Printf
}
}
3.用在逻辑表达式中
func main() {
// 3.用在逻辑表达式中
Age := 18
gender := "男"
if Age >= 18 && gender == "男" {
fmt.Println("你是成年男子!")
}
}
注意:不能使用
0和非0表示真假
func main() {
i := 1
if i {
// 编译错误
}
}
6.5 其他数字类型
以下列出了其他更多的数字类型:
| 数据类型 | 描述 |
|---|---|
| byte | 类似 uint8 |
| rune | 类似 int32 |
| uint 32 或 64 位 | uint 32 或 64 位 |
| int | 与 uint 一样大小 |
| uintptr | 无符号整型,用于存放一个指针 |
7 字符串
一个Go语言字符串是一个任意字节的常量序列。
字符串就是byte类型的字节数组—[] byte
7.1 字符串字面量
在Go语言中,字符串字面量使用双引号 "" 或者反引号 ' 创建。双引号用来创建可解析的字符串,支持转义,但不能用来引用多行;反引号用来创建原生的字符串字面量,可能由多行组成,但不支持转义,并且可以包含除了反引号外其他所有字符。双引号创建可解析的字符串应用最广泛,反引号用来创建原生的字符串则多用于书写多行消息,HTML以及正则表达式。
func main() {
var str1 string = "你好,中国!"
var str2 = "Hello,Golang!"
str3 := "Golang,Java,C#..."
str4 := `
<html>
<head><title>Hello golang!</title>
</html>
`
fmt.Printf("str1: %v\n", str1)
......
}
7.2 字符串连接
7.2.1 加号
虽然Go语言中的字符串是不可变的,但是字符串支持 + 级联操作和+=追加操作。
func main() {
// 1.字符串连接--使用加号
name := "小罗"
age := "30"
msg := name + " " + age
fmt.Printf("msg: %v\n", msg)
fmt.Println("-------------")
msg = ""
msg += name
msg += " "
msg += age
fmt.Printf("msg: %v\n", msg)
}
Golang 里面的字符串都是不可变的,每次运算都会产生一个新的字符串,所以会产生很多临时的无用的字符串,不仅没有用,还会给 gc 带来额外的负担,所以性能比较差。
7.2.2 fmt.Sprintf()函数
func main() {
// 2.字符串连接--fmt.Sprintf()函数
Name := "小罗"
Age := "30"
Msg := fmt.Sprintf("Name=%s,Age=%s", Name, Age)
fmt.Printf("msg: %v\n", Msg)
}
内部使用
[]byte实现,不像直接运算符这种会产生很多临时的字符串,但是内部的逻辑比较复杂,有很多额外的判断,还用到了interface,所以性能也不是很好。
7.2.3 strings.Join()
func main() {
// 3.字符串连接--strings.Join()方法
nAme := "小罗"
aGe := "30"
mSg := strings.Join([]string{nAme, aGe}, ",")
fmt.Printf("mSg: %v\n", mSg)
}
join会先根据字符串数组的内容,计算出一个拼接之后的长度,然后申请对应大小的内存,一个一个字符串填入,在已有一个数组的情况下,这种效率会很高,但是本来没有,去构造这个数据的代价也不小。
7.2.4 buffer.WriteString()
func main() {
// 4.字符串连接--buffer.WriteString()方法
var buffer bytes.Buffer
buffer.WriteString("小罗")
buffer.WriteString(",")
buffer.WriteString("30")
fmt.Printf("buffer.String(): %v\n", buffer.String())
}
这个比较理想,可以当成可变字符使用,对内存的增长也有优化,如果能预估字符串的长度,还可以用
buffer.Grow()接口来设置 capacity。
7.3 转义字符
Go语言的字符串常见转义字符包括:回车、换行、单双引号、制表符等,如下所示:
| 转义字符 | 含义 |
|---|---|
\r |
回车符(返回行首) |
\n |
换行符(直接跳到下一行的同列位置) |
\t |
制表符 |
\' |
单引号 |
\" |
双引号 |
\\ |
反斜杠 |
func main() {
// 5.字符串转义字符
fmt.Print("Hello\tworld\n")
fmt.Print("\"c:\\test\\a\"")
}
// 输出结果: Hello world "c:\test\a"
7.4 字符串切片操作
Go 里字符串底层是 byte 切片,str[n] 取出的是 byte 类型(本质是uint8 数字):
%v 通用格式化:直接打印 byte 对应字符串的ASCII 码值(十进制数字)
%c 专门用来把数值转成对应字符打印出来(肉眼看到的文字/符号)
func main() {
str := "Hi,Golang!"
n := 3
m := 5
fmt.Println("字符串str的字节长度len(str):", len(str))
runeStr := []rune(str)
fmt.Println("字符串str的字符长度len([]runeStr):", len(runeStr))
fmt.Printf("str[n]: %v\n", str[n]) // 获取字符串索引位置为n的原始字节
fmt.Printf("str[n]: %c\n", str[n])
fmt.Printf("str[n:m]: %v\n", str[n:m]) // 截取字符串索引位置为n到m-1的字符串
fmt.Printf("str[n:]: %v\n", str[n:]) // 截取字符串索引位置为n到len(str)-1的字符串
fmt.Printf("str[:m]: %v\n", str[:m]) // 截取字符串索引位置为0到m-1的字符串
}
7.5 字符串长度
1.取字节长度(英文/数字正常,中文不准)--- len(str)
原理:Go 字符串是 UTF-8 字节流,len() 统计字节个数
英文/字母/数字:1个字符 = 1字节,长度正常
中文:1个汉字占 3字节,len() 结果会偏大
s1 := "你好go"
fmt.Println(len(s1)) // 输出8,不是4个字符
2.取字符个数(真正汉字、字母总个数)--- 用rune转切片:
s2 := "你好Go语言"
fmt.Println("字符串s2的字节长度len(s2):", len(s2))
runeSlice := []rune(s2)
fmt.Println("字符串s2的字符长度len([]runeSlice):", len(runeSlice))
3.简洁一行写法 length := len([]rune(s))
4.总结:
要字节长度(存文件、网络传输):用 len(str)
要实际字符个数(展示、排版、截取):用 len([]rune(str))
7.6 字符串常用方法
| 方法 | 介绍 |
|---|---|
| len(str) | 求长度 |
| +或fmt.Sprintf | 拼接字符串 |
| strings.Split | 分割 |
| strings.contains | 判断是否包含 |
| strings.HasPrefix,strings.HasSuffix | 前缀/后缀判断 |
| strings.Index(),strings.LastIndex() | 子串出现的位置 |
| strings.ToUpper(),strings.ToLower() | 大小写转换 |
| strings.Join(a[]string, sep string) | join操作 |
func main() {
// 字符串常用方法
Gostr := "Hello,Go语言!"
fmt.Printf("len(Gostr):%v\n", len(Gostr))
fmt.Printf("strings.Split(Gostr, \" \"): %v\n", strings.Split(Gostr, ",")) // 按逗号(,)分割
fmt.Printf("strings.Contains(Gostr, \"语言\"): %v\n", strings.Contains(Gostr, "语言")) // 是否包含语言
fmt.Printf("strings.HasPrefix(Gostr, \"Hello\"): %v\n", strings.HasPrefix(Gostr, "Hello")) // 前缀判断
fmt.Printf("strings.HasSuffix(Gostr, \"语言\"): %v\n", strings.HasSuffix(Gostr, "语言")) // 后缀判断
fmt.Printf("strings.Index(Gostr, \"Hello\"): %v\n", strings.Index(Gostr, "Hello")) // 子串出现的位置
fmt.Printf("strings.LastIndex(Gostr, \"Go\"): %v\n", strings.LastIndex(Gostr, "Go")) // 子串出现的位置
fmt.Printf("strings.ToLower(Gostr): %v\n", strings.ToLower(Gostr)) // 转换为小写
fmt.Printf("strings.ToUpper(Gostr): %v\n", strings.ToUpper(Gostr)) // 转换为大写
}
8 byte和rune类型
组成每个字符串的元素叫做“字符”,可以通过遍历或者单个获取字符串元素获得字符。 字符用单引号(’)包裹起来,如:
func main() {
// byte和rune类型
var t = '中'
var k = 'b'
fmt.Printf("t: %v,%c\n", t, t)
fmt.Printf("k: %v,%c\n", k, k)
}
Go 语言的字符有以下两种:
1.uint8类型,或者叫 byte 型,代表了ASCII码的一个字符。
2.rune类型,代表一个 UTF-8字符。
当需要处理中文、日文或者其他复合字符时,则需要用到rune类型。rune类型实际是一个int32。
Go使用了特殊的rune类型处理Unicode,让基于Unicode的文本处理更为方便,也可以使用byte型进行默认字符串处理,性能和扩展性都有照顾。
9 Golang格式化输出
下面实例使用到的结构体:
// 快捷方式---tys
type webSite struct {
Name string
}
func main() {
// Golang的结构化输出
// 定义结构体变量
// var site = webSite{Name: "linuxtech.top"}
site := webSite{Name: "linuxtech.top"}
}
9.1 普通占位符
| 占位符 | 说明 | 举例 | 输出 |
|---|---|---|---|
| %v | 相应值的默认格式 | fmt.Printf(“site: %v\n”, site) | site: {linuxtech.top} |
| %+v | “加号”标记(%+v)会添加字段名 | fmt.Printf(“site: %+v\n”, site) | site: {Name:linuxtech.top} |
| %#v | 相应值的Go语法表示 | fmt.Printf(“site: %#v\n”, site) | site: main.webSite{Name:”linuxtech.top”} |
| %T | 相应值的类型的Go语法表示 | fmt.Printf(“site: %T\n”, site) | site: main.webSite |
| %% | 字面上的百分号,并非值的占位符 | fmt.Printf(“site: %%\n”, site) | site: %% |
9.2 布尔占位符
| 占位符 | 说明 | 举例 | 输出 |
|---|---|---|---|
| %t | 单词 true 或 false。 | fmt.Printf(“b: %t\n”, b) | b: true |
func main() {
b := true
fmt.Printf("b: %t\n", b)
}
9.3 整数占位符
| 占位符 | 说明 | 举例 | 输出 |
|---|---|---|---|
| %b | 二进制表示 | fmt.Printf(“%b\n”, 5) | 101 |
| %c | 相应Unicode码点所表示的字符 | fmt.Printf(“%c\n”, 0x4E2D) | 中 |
| %d | 十进制表示 | fmt.Printf(“%d\n”, 0x12) | 18 |
| %o | 八进制表示 | fmt.Printf(“%o\n”, 10) | 12 |
| %q | 单引号围绕的字符字面值,由Go语法安全地转义 | fmt.Printf(“%q\n”, 0x4E2D) | ‘中’ |
| %x | 十六进制表示,字母形式为小写 a-f | fmt.Printf(“%x\n”, 13) | d |
| %X | 十六进制表示,字母形式为大写 A-F | fmt.Printf(“%x\n”, 13) | d |
| %U | Unicode格式:U+1234,等同于 “U+%04X” | fmt.Printf(“%U\n”, 0x4E2D) | U+4E2D |
9.4 实部和虚部
| 占位符 | 说明 | 举例 | 输出 |
|---|---|---|---|
| %b | 无小数部分的,指数为二的幂的科学计数法, 与 strconv.FormatFloat的 ‘b’ 转换格式一致。例如 -123456p-78 |
fmt.Printf(“%b\n”, 10.2) | 5742089524897382p-49 |
| %e | 科学计数法,例如 -1234.456e+78 | fmt.Printf(“%e\n”, 10.2) | 1.020000e+01 |
| %E | 科学计数法,例如 -1234.456E+78 | fmt.Printf(“%E\n”, 10.2) | 1.020000E+01 |
| %f | 有小数点而无指数,例如 123.456 | fmt.Printf(“%f\n”, 10.2) | 10.200000 |
| %g | 根据情况选择 %e 或 %f 以产生更紧凑的(无末尾的0)输出 | fmt.Printf(“%g\n”, 10.20) | 10.2 |
| %G | 根据情况选择 %E 或 %f 以产生更紧凑的(无末尾的0)输出 | fmt.Printf(“%G\n”, 10.20+2i) | (10.2+2i) |
9.5 字符串与字节切片
| 占位符 | 说明 | 举例 | 输出 |
|---|---|---|---|
| %s | 输出字符串表示(string类型或[]byte) | fmt.Printf(“%s\n”, []byte(“中国政府网”)) | 中国政府网 |
| %q | 双引号围绕的字符串,由Go语法安全地转义 | fmt.Printf(“%q\n”, “中国政府网”) | “中国政府网” |
| %x | 十六进制,小写字母,每字节两个字符 | fmt.Printf(“%x\n”, “中国政府网”) | e4b8ade59bbde694bfe5ba9ce7bd91 |
| %X | 十六进制,大写字母,每字节两个字符 | fmt.Printf(“%X\n”, “中国政府网”) | E4B8ADE59BBDE694BFE5BA9CE7BD91 |
9.6 指针
| 占位符 | 说明 | 举例 | 输出 |
|---|---|---|---|
| %p | 十六进制表示,前缀 0x | fmt.Printf(“%p”, &site) | 0x3ab4cdd1c030 |
10 运算符
Go语言内置的运算符有:算术运算符、关系运算符、逻辑运算符、位运算符、赋值运算符
10.1 算术运算符
| 运算符 | 描述 |
|---|---|
| + | 相加 |
| - | 相减 |
| * | 相乘 |
| / | 相除 |
| % | 求余 |
++(自增)和--(自减)在Go语言中是单独的语句,并不是运算符。
func main() {
a := 100
b := 10
fmt.Printf("(a + b): %v\n", (a + b))
fmt.Printf("(a - b): %v\n", (a - b))
fmt.Printf("(a * b): %v\n", (a * b))
fmt.Printf("(a / b): %v\n", (a / b))
fmt.Printf("(a %% b): %v\n", (a % b))
a++
fmt.Printf("a: %v\n", a)
b--
fmt.Printf("b: %v\n", b)
}
10.2 关系运算符
| 运算符 | 描述 |
|---|---|
| == | 检查两个值是否相等,如果相等返回 True 否则返回 False。 |
| != | 检查两个值是否不相等,如果不相等返回 True 否则返回 False。 |
| > | 检查左边值是否大于右边值,如果是返回 True 否则返回 False。 |
| >= | 检查左边值是否大于等于右边值,如果是返回 True 否则返回 False。 |
| < | 检查左边值是否小于右边值,如果是返回 True 否则返回 False。 |
| <= | 检查左边值是否小于等于右边值,如果是返回 True 否则返回 False。 |
func main() {
m := 1
n := 2
fmt.Printf("(m > n): %v\n", (m > n))
fmt.Printf("(m < n): %v\n", (m < n))
fmt.Printf("(m >= n): %v\n", (m >= n))
fmt.Printf("(m <= n): %v\n", (m <= n))
fmt.Printf("(m == n): %v\n", (m == n))
fmt.Printf("(m != n): %v\n", (m != n))
}
10.3 逻辑运算符
| 运算符 | 描述 |
|---|---|
| && | 逻辑 AND 运算符。 如果两边的操作数都是 True,则为 True,否则为 False。 |
| \ | \ |
| ! | 逻辑 NOT 运算符。 如果条件为 True,则为 False,否则为 True。 |
func main() {
p := true
q := false
fmt.Printf("(p && q): %v\n", (p && q))
fmt.Printf("(p || q): %v\n", (p || q))
fmt.Printf("(!p): %v\n", (!p))
fmt.Printf("(!q): %v\n", (!q))
}
10.4 位运算符
位运算符对整数在内存中的二进制位进行操作。
| 运算符 | 描述 |
|---|---|
| & | 参与运算的两数各对应的二进位相与。 (两位均为1才为1) |
| \ | |
| ^ | 参与运算的两数各对应的二进位相异或,当两对应的二进位相异时,结果为1。 (两位不一样则为1) |
| << | 左移n位就是乘以2的n次方。 “a<<b”是把a的各二进位全部左移b位,高位丢弃,低位补0。 |
| >> | 右移n位就是除以2的n次方。 “a>>b”是把a的各二进位全部右移b位。 |
func main() {
a := 4 // 二进制 100
fmt.Printf("a: %b\n", a)
b := 8 // 二进制 1000
fmt.Printf("b: %b\n", b)
fmt.Printf("(a & b): %v, %b \n", (a & b), (a & b))
fmt.Printf("(a | b): %v, %b\n", (a | b), (a | b))
fmt.Printf("(a ^ b): %v, %b\n", (a ^ b), (a ^ b))
fmt.Printf("(a << 2): %v, %b\n", (a << 2), (a << 2))
fmt.Printf("(b >> 2): %v, %b\n", (b >> 2), (b >> 2))
}
10.5 赋值运算符
| 运算符 | 描述 |
|---|---|
| = | 简单的赋值运算符,将一个表达式的值赋给一个左值 |
| += | 相加后再赋值 |
| -= | 相减后再赋值 |
| *= | 相乘后再赋值 |
| /= | 相除后再赋值 |
| %= | 求余后再赋值 |
| <<= | 左移后赋值 |
| >>= | 右移后赋值 |
| &= | 按位与后赋值 |
| \ | = |
| ^= | 按位异或后赋值 |
func main() {
var a int
a = 100
fmt.Printf("a: %v\n", a)
a += 1 // a = a + 1
fmt.Printf("a: %v\n", a)
a -= 1 // a = a -1
fmt.Printf("a: %v\n", a)
a *= 2 // a = a * 2
fmt.Printf("a: %v\n", a)
a /= 2 // a = a / 2
fmt.Printf("a: %v\n", a)
}