变量、常量与数据类型


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
print 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 也有基于架构的类型,例如:intuintuintptr

  类型的长度是根据运行程序所在的操作系统类型所决定的

   intuint 在 32 位操作系统上,均使用 32 位(4 个字节),在 64 位操作系统上使用 64 位(8 个字节)。

   uintptr 的长度被设定为足够存放一个指针即可。

  Go 语言中没有 float 类型。

  Go语言中只有 float32float64,没有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语言支持两种浮点型数:float32float64,这两种浮点型数据格式遵循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语言中的布尔类型有两个常量值:truefalse。布尔类型经常用在条件判断语句循环语句,也可用在逻辑表达式中。

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

文章作者: 罗宇
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 罗宇 !
 上一篇
基础入门 基础入门
Go(Golang)是Google开发的一种静态强类型、编译型语言。语法与C相近,但功能上有:内存安全、GC(垃圾回收),结构形态及CSP-style并发计算。
下一篇 
流程控制语句 流程控制语句
Go(Golang)是Google开发的一种静态强类型、编译型语言。语法与C相近,但功能上有:内存安全、GC(垃圾回收),结构形态及CSP-style并发计算。
  目录