1、运行和解析
go run 命令已包含了编译和运行。它会先在一个临时目录编译程序,然后执行完后清理掉.
如果在run的后面加上 --work参数来查看临时目录。

go run --work  main.go

Go语言学习-LMLPHP
也可以通过go build命令来编译代码,执行后会生成一个可以执行文件,通过./XX直接执行
Go语言学习-LMLPHP
交叉编译

# 要去linux下执行 
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build main.go
# 要去Mac下执行 
CGO_ENABLED=0 GOOS=darwin GOARCH=amd64 go build main.go
# 要去win下执行
CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build main.go

CGO_ENABLED : CGO 表示golang中的工具,CGO_ENABLED 表示CGO禁用,交叉编译中不能使用CGO的

GOOS
目标平台
mac 对应 darwin
linux 对应 linux
windows 对应 windows

GOARCH
目标平台的体系架构【386,amd64,arm】, 目前市面上的个人电脑一般都是amd64架构的
386 也称 x86 对应 32位操作系统
amd64 也称 x64 对应 64位操作系统
arm 这种架构一般用于嵌入式开发。 比如 Android , IOS , Win mobile , TIZEN 等

变量类型:整型、浮点型、布尔型
变量声明:
标准声明 var 变量名称 变量类型 不需要分号
批量声明 var (变量名称 变量类型
变量名称 变量类型
变量名称 变量类型
… …)
变量初始化 var 变量名 类型 = 表达式 ,其中整型和浮点型变量默认值为0,布尔型变量默认为false,
初始化多个变量 var 变量名,变量名… = 表达式,表达式…
类型推导 var 变量名 = 表达式 ,编译器会根据表达式的值来推导变量名的类型并完成初始化
短变量声明 变量名 := 表达式
匿名变量 _一个下划线来表示
注意事项:
函数外的每个语句都必须以关键字开始(var、const、func等)
:=不能使用在函数外。
_多用于占位,表示忽略值。
常量 const
iota 常量计数器,在const关键字出现时将被重置为0。const中每新增一行常量声明将使iota计数一次
定义数量级 << 左移操作
多个iota定义在一行
基本类型
bool (布尔)
数值类型 分为有符号数和无符号数,有符号数可以用来表示负数,不同的位数代表它们实际存储占用空间,以及取值的范围
int8、int16、int32、int64、int
uint8、uint16、uint32、uint64、uint
float32, float64
complex64, complex128
byte
rune
string
类型转换,对显式类型非常严格,没有自动类型提升或转换

循环条件
For 循环语句用于重复执行一段代码,是 Go 中唯一可用的循环
for initialisation; condition; post {
}
break语句用于在 for 循环完成正常执行之前突然终止 for 循环,并将控件移动到 for 循环之后的代码行。
continue语句用于跳过 for 循环的当前迭代。在 continue 语句之后出现在 for 循环中的所有代码都不会在当前迭代中执行。循环将继续进行下一次迭代。

if else 是一个具有布尔条件的语句,如果该条件的计算结果为真 ,它将执行一段代码true。如果条件评估为 ,它会执行一个备用的 else 块false。

swich 是一个条件语句,它计算表达式并将其与可能匹配的列表进行比较并执行相应的代码块,switch 只要匹配中了就会中止剩余的匹配项,switch 的 case 条件可以是多个值, 同一个 case 中的多值不能重复。

数组 具有相同 唯一类型 的一组以编号且长度固定的数据项序列,数据的长度是固定的。我们在声明一个数组时需要指定它的长度,一旦指定了长度,那么它的长度值是不可以改变的。
数组声明,一个数组的表示形式为 T[n]。n 表示数组中元素的数量,T 代表每个元素的类型,可以忽略声明数组的长度,并用 … 代替,让编译器为你自动计算长度。
数组是值类型,而不是引用类型,当数组赋值给一个新的变量时,该变量会得到一个原始数组的一个副本,如果对新变量进行更改,则不会影响原始数组。

	o := [...]float64{67.4, 89.3, 21, 77}
	for i := 0; i < len(o); i++ {
		fmt.Println("%d th element of a is %.2f\n", i, o[i])
	}

使用 range 遍历数组 ,for 循环可用于遍历数组中的元素,range 返回索引和该索引处的值
for i, v := range a 利用的是 for 循环 range 方式
多维数组  [][] 数据类型 {}
j := [2][3]string{
		{"li", "wang", "oi"},
		{"cao", "sun", "hg"},
	}

	for _, v1 := range j {
		for _, v2 := range v1 {
			fmt.Println("%s", v2)
		}
	}

切片是对数组一个连续片段的引用,是一个引用类型,是一个长度可变的数组,具有 T 类型元素的切片表示为[]T
使用语法 a[start:end] 创建一个从 a 数组索引 start 开始到 end - 1 结束的切片

a := [5]int{76, 77, 78, 79, 80}
	var b []int = a[1:4]
	fmt.Println(a)
	fmt.Println(b)

切片的修改:切片自己不拥有任何数据。它只是底层数组的一种表示。对切片所做的任何修改都会反映在底层数组中。

a := [5]int{76, 77, 78, 79, 80}
	var b []int = a[1:4]
	fmt.Println(a)
	fmt.Println(b)
	for g := range b {
		b[g]++
	}
	fmt.Println(a)

切片的长度和容量:
切片的长度是切片中的元素数。切片的容量是从创建切片索引开始的底层数组中元素数。

funarry := [...]string{"1", "2", "3", "4", "5"}
	funlist := funarry[1:4]
	fmt.Println(len(funlist), cap(funlist))

切片可以重置其容量。任何超出这一点将导致程序运行时抛出错误。

	funarry := [...]string{"1", "2", "3", "4", "5"}
	funlist := funarry[1:4]
	fmt.Println(len(funlist), cap(funlist))
	funlist = funlist[:cap(funlist)]
	fmt.Println(len(funlist), cap(funlist))

func make([]T,len,cap)[]T 通过传递类型,长度和容量来创建切片。容量是可选参数, 默认值为切片长度。make 函数创建一个数组,并返回引用该数组的切片。

r := make([]int, 5, 6)
	fmt.Println(r)

追加切片元素,使用 append 可以将新元素追加到切片上。append 函数的定义是 func append(s[]T,x … T)[]T。x … T 在函数定义中表示该函数接受参数 x 的个数是可变的。这些类型的函数被称为可变参函数。

car := []string{"福田", "宝马", "奔驰"}
	fmt.Println(car,len(car),cap(car))
	car = append(car, "雷克萨斯")
	fmt.Println(car,len(car),cap(car))

切片函数传递,切片包含长度、容量和指向数组第零元素的指针,切片原有空间不够时自动新建底层数组, 小于 1024, 新的容量直接翻倍增加

func subtactone(number []int) {
	for i := range number {
		number[i] -= 2
	}
}

nos := []int{8, 7, 6}
	fmt.Println(nos)
	subtactone(nos)
	fmt.Println(nos)

多维切片,与数组类似,可以有多个维度

pos := [][]string{
		{"c++", "java"},
		{"python", "goland"},
	}
	for _, v1 := range pos {
		for _, v2 := range v1 {
			fmt.Println(v2)
		}
	}

map 一种无序的键值对, 它是数据结构 hash 表的一种实现方式
map[type of key]type of value{xxxxxxxx}
make(map[type of key]type of value)

look := map[string]int{"code": 1, "msg": 333}
	fmt.Println(look)
	cm := make(map[string]int)
	cm["name"] = 22
	fmt.Println(cm)

map的零值是nil

var say map[string]int
	say["code"] = 10000
panic: assignment to entry in nil map

检索建的值 map[key]

citys := map[string]int{
		"北京": 110000,
		"广东": 430000,
	}
	city := "北京"
	postCode := citys[city]
	fmt.Println(city, postCode)

该映射将返回该元素类型的零值, 0 当我们尝试检索 Map中不存在的键的值时,不会出现运行时错误

citys := map[string]int{
		"北京": 110000,
		"广东": 430000,
	}
	city := "北京1"
	postCode := citys[city]
	fmt.Println(city, postCode)

检查键值是否存在 value, ok := map[key]

citys := map[string]int{
		"北京": 110000,
		"广东": 430000,
	}
	city := "北京"
	value, ok := citys[city]
	if ok == true {
		fmt.Println(value)
		postCode := citys[city]
		fmt.Println(city, postCode)
	}

遍历map中的所有元素 for循环的range形式用于迭代 Map的所有元素。

citys := map[string]int{
		"北京": 110000,
		"广东": 430000,
	}

	for key, value := range citys {
		fmt.Println(key, value)
	}

从map中删除元素 delete(map,key),函数没有返回值,删除 Map中不存在的键,则不会出现运行时错误。

citys := map[string]int{
		"北京": 110000,
		"广东": 430000,
	}

	delete(citys, "北京")

	for key, value := range citys {
		fmt.Println(key, value)
	}

与切片一样,maps 是引用类型。当一个 map 赋值给一个新的变量,它们都指向同一个内部数据结构。因此改变其中一个也会反映到另一个。
须指定 key, value 的类型,插入的纪录类型必须匹配。
key 具有唯一性,插入纪录的 key 不能重复。
KeyType 可以为基础数据类型(例如 bool, 数字类型,字符串), 不能为数组,切片,map,它的取值必须是能够使用 == 进行比较。
ValueType 可以为任意类型。
无序性。
线程不安全, 一个 goroutine 在对 map 进行写的时候,另外的 goroutine 不能进行读和写操作,Go 1.6 版本以后会抛出 runtime 错误信息。

字符串string,通过将一组字符括在双引号中来创建字符串" "

%s 是打印字符串的格式说明符
%x 是十六进制的格式说明符
%b 是二进制的格式说明符
%d 是十进制的格式说明符
%o 是八进制的格式说明符
%t true或false
%c 格式说明符用于在printChars方法中打印字符串的字符
%T是用来输出数据类型的格式化占位符
%v输出所有的值信息

web := "https:www.gotribe.cn"
	fmt.Println(web)

字符串的单个字节

web := "https:www.gotribe.cn"
	fmt.Println(web)

	for i := 0; i < len(web); i++ {
		fmt.Println(web[i])
	}

在 UTF-8 编码中,一个码点可能会占一个以上的字节
rune 是Go 中的内置类型,它是 int32 的别名。Rune 表示 Go 中的 Unicode 代码点。代码点占用多少字节并不重要,它可以用一个符文来表示

web := "Señor"
	runes := []rune(web)
	for i := 0; i < len(runes); i++ {
		fmt.Printf("%c ", runes[i])
	}

字符串连接
使用+运算符

string1 := "1"
	string2 := "2"
	result := string1 + string2
	fmt.Println(result)
使用 fmt 包的Sprintf函数
string1 := "1"
	string2 := "2"
	string3 := "3"
	result := fmt.Sprintf("%x %x %s", string1, string2, string3)
	fmt.Println(result)

函数 是执行特定任务的代码块

func name(parameter) (result-list){
    //body
}

函数声明以func关键字开头,后跟name(函数名). 在括号中指定参数,后面为函数返回值result-list
指定参数的语法是,参数名称后跟类型。可以指定任意数量的参数,例如(parameter1 type, parameter2 type)。而{,}内的代码为函数的主体内容。
函数组成
函数名
参数列表(parameter)
返回值(result-list)
函数体(body)
参数和返回类型在函数中是可选的

单返回值函数

func plus(a, b int) (res int) {
	return a + b
}

count := plus(1, 3)
	fmt.Println(count)

多返回值函数,一个函数可以返回多个值

func multi() (string, int) {
	return "网", 2
}
name, age = multi()
	fmt.Println(name, age)

命名返回值,从函数返回命名值。如果返回值被命名,则可以认为它在函数的第一行被声明为变量。

func nameValue() (name string, height int) {
	// name = "王"
	// height = 110
	return
}

name, height := nameValue()
	fmt.Println(name, height)

参数可变函数

func sum(nums ...int) int {
	res := 0
	for _, v := range nums {
		res += v
	}
	return res
}
fmt.Println(sum(1))
	fmt.Println(sum(1, 2))
	fmt.Println(sum(1, 2, 3))

匿名函数

func(name string) {
		fmt.Println(name)
	}("web")
12-29 12:13