[GO]Golang的一些特有基础语法
1.下划线
下划线的作用是用来接收一个变量,并且不对其进行操作.
比如os.Open,返回值为*os.File,error.
普通写法:
f,err := os.Open("xxxxxxx")
如果此时不需要知道返回的错误值 就可以用
f, _ := os.Open("xxxxxx")
如此则忽略了error变量.这样编译器可以更好的优化,任何类型的单个值都可以丢给下划线。
2.变量声明的形式
Go语言的变量声明格式为:
var 变量名 变量类型
Go语言在声明变量的时候,会自动对变量对应的内存区域进行初始化操作。每个变量会被初始化成其类型的默认值,例如: 整型和浮点型变量的默认值为0。 字符串变量的默认值为空字符串。 布尔型变量默认为false
。 切片、函数、指针变量的默认为nil
。
可以在声明的时候同时进行初始化:
var 变量名 类型 = 表达式
有时候我们会将变量的类型省略,这个时候编译器会根据等号右边的值来推导变量的类型完成初始化。
var 变量名 = 表达式
在函数内部,可以使用更简略的 := 方式声明并初始化变量。这种:=声明方式不能用于函数外.
func main() { n := 10 //短声明方式 m := 200 fmt.Println(m, n) }
匿名变量:在使用多重赋值时,如果想要忽略某个值,可以使用匿名变量,用一个下划线_表示,匿名变量不占用命名空间,不会分配内存,所以匿名变量之间不存在重复声明。
func foo() (int, string) { return 10, "test" } func main() { x, _ := foo() _, y := foo() fmt.Println("x=", x) fmt.Println("y=", y) }
3.Golang的字符,字符串和切片
Golang的字符串底层是一个byte数组,所以可以和[]byte类型相互转换。字符串是不能修改的 字符串是由byte字节组成,所以字符串的长度是byte字节的长度。
要修改字符串,需要先将其转换成[]rune或[]byte
,完成后再转换为string
。无论哪种转换,都会重新分配内存,并复制字节数组。
func changeString() { s1 := "hello" // 强制类型转换 转为切片byteS1 byteS1 := []byte(s1) byteS1[0] = 'H' fmt.Println(string(byteS1)) //rune 类型是一种特殊的int32 用于处理中文等情况 s2 := "博客" runeS2 := []rune(s2) runeS2[0] = '波' fmt.Println(string(runeS2)) }
4.Golang的数组
1.数组:是同一种数据类型的固定长度的序列。
2.数组定义:var a [len]int,比如:var a [5]int,数组长度必须是常量,且是类型的组成部分。一旦定义,长度不能变。
3.长度是数组类型的一部分,因此,var a[5] int和var a[10]int是不同的类型。
4.数组可以通过下标进行访问,下标是从0开始,最后一个元素下标是:len-1
for i := 0; i < len(a); i++ { } for index, v := range a { }
5.访问越界,如果下标在数组合法范围之外,则触发访问越界,会panic
6.数组是值类型,赋值和传参会复制整个数组,而不是指针。因此改变副本的值,不会改变本身的值。
7.支持 "=="、"!=" 操作符,因为内存总是被初始化过的。
8.指针数组 [n]*T,数组指针 *[n]T。
数组初始化的几种方式
var arr0 [5]int = [5]int{1, 2, 3} var arr1 = [5]int{1, 2, 3, 4, 5} var arr2 = [...]int{1, 2, 3, 4, 5, 6} var str = [5]string{3: "hello world", 4: "tom"} a := [3]int{1, 2} // 未初始化元素值为 0。 b := [...]int{1, 2, 3, 4} // 通过初始化值确定数组长度。 c := [5]int{2: 100, 4: 200} // 使用索引号初始化元素。 d := [...]struct { name string age uint8 }{ {"user1", 10}, // 可省略元素类型。 {"user2", 20}, // 别忘了最后一行的逗号。 }
var arr0 [5][3]int
var arr1 [2][3]int = [...][3]int{{1, 2, 3}, {7, 8, 9}}
a := [2][3]int{{1, 2, 3}, {4, 5, 6}}
b := [...][2]int{{1, 1}, {2, 2}, {3, 3}} // 第 2 纬度不能用 "..."。
5.Golang的切片
slice 并不是数组或数组指针。它通过内部指针和相关属性引用数组片段,以实现变长方案。
1.切片:切片是数组的一个引用,因此切片是引用类型。但自身是结构体,值拷贝传递。
2.切片的长度可以改变,因此,切片是一个可变的数组。
3.切片遍历方式和数组一样,可以用len()求长度。表示可用元素数量,读写操作不能超过该限制。
4.cap可以求出slice最大扩张容量,不能超出数组限制。0 <= len(slice) <= len(array),其中array是slice引用的数组。
5.切片的定义:var 变量名 []类型,比如 var str []string或var arr []int。
6.如果 slice == nil,那么 len、cap 结果都等于 0。
切片的声明形式:
func main() { //1.声明切片 var s1 []int if s1 == nil { fmt.Println("是空") } else { fmt.Println("不是空") } // 2.:= s2 := []int{} // 3.make() var s3 []int = make([]int, 0) fmt.Println(s1, s2, s3) // 4.初始化赋值 var s4 []int = make([]int, 0, 0) fmt.Println(s4) s5 := []int{1, 2, 3} fmt.Println(s5) // 5.从数组切片 arr := [5]int{1, 2, 3, 4, 5} var s6 []int // 前包后不包 s6 = arr[1:4] fmt.Println(s6) }
使用 make 动态创建slice,避免了数组必须用常量做长度的麻烦。还可用指针直接访问底层数组,退化成普通数组操作。通过make创建切片:
var slice []type = make([]type, len) slice := make([]type, len) //省略cap,相当于len=cap slice := make([]type, len, cap)
注意,这时对切片进行操作等于对底层数组进行操作.
6.Golang的字符数组
string底层就是一个byte的数组,因此,也可以进行切片操作。
package main import ( "fmt" ) func main() { str := "hello world" s1 := str[0:5] fmt.Println(s1) s2 := str[6:] fmt.Println(s2) }
// 输出结果
//hello
// world