title: go基础
date: 2023-5-12
什么是go语言
变量常量
命名必须以一个字母或下划线开头
变量的声明
var a = "initial"
var b, c int = 1, 2
var d = true
var e float64
f := float32(e)
g := a + "foo"
常量的声明
const s string = "constant"
const h = 500000000
const i = 3e20 / h
new函数
表达式new(T)将创建一个T类型的匿名变量,初始化为T类型的零值,然后返回变量地址,返回的指针类型为*T
p := new(int) // p, *int 类型, 指向匿名的 int 变量
fmt.Println(*p) // "0"
*p = 2 // 设置 int 匿名变量的值为 2
fmt.Println(*p) // "2"
new函数类似是一种语法糖,而不是一个新的基础概念
func newInt() *int {
return new(int)
}
// 这两个newInt函数有着相同的行为
func newInt() *int {
var dummy int
return &dummy
}
赋值
x = 1 // 命名变量的赋值
*p = true // 通过指针间接赋值
person.name = "bob" // 结构体字段赋值
count[x] = count[x] * scale // 数组、slice或map的元素赋值
基础语法
-
if else
if num := 9; num < 0 { fmt.Println(num, "is negative") } else if num < 10 { fmt.Println(num, "has 1 digit") } else { fmt.Println(num, "has multiple digits") } -
switch
a := 2 switch a { case 1: fmt.Println("one") case 4, 5: fmt.Println("four or five") default: fmt.Println("other") } t := time.Now() switch { case t.Hour() < 12: fmt.Println("It's before noon") default: fmt.Println("It's after noon") } -
数组
数组是一个由固定长度的特定类型元素组成的序列,一个数组可以由零个或多个元素组成
在数组字面值中,如果在数组的长度位置出现的是“...”省略号,则表示数组的长度是根据初始化值的个数来计算。
q := [...]int{1, 2, 3} fmt.Printf("%T\n", q) // "[3]int"因为数组的长度是固定的,因此在Go语言中很少直接使用数组
func main(){ var a [5]int a[4] = 100 var twoD [2][3]int for i := 0; i < 2; i++ { for j := 0; j < 3; j++ { twoD[i][j] = i + j } } } -
切片
切片代表变长的序列,序列中每个元素都有相同的类型
func main() { s := make([]string, 3) s[0] = "a" s[1] = "b" s[2] = "c" fmt.Println("get:", s[2]) // c fmt.Println("len:", len(s)) // 3 s = append(s, "d") s = append(s, "e", "f") fmt.Println(s) // [a b c d e f] c := make([]string, len(s)) copy(c, s) fmt.Println(c) // [a b c d e f] fmt.Println(s[2:5]) // [c d e] fmt.Println(s[:5]) // [a b c d e] fmt.Println(s[2:]) // [c d e f] good := []string{"g", "o", "o", "d"} fmt.Println(good) // [g o o d] }测试一个slice是否是空的,使用len(s) == 0来判断,而不应该用s == nil来判断
var s []int // len(s) == 0, s == nil s = nil // len(s) == 0, s == nil s = []int(nil) // len(s) == 0, s == nil s = []int{} // len(s) == 0, s != nil= -
map
map是一个无序的key/value对的集合,其中所有的key都是不同的,然后通过给定的key可以在常数时间复杂度内检索、更新或删除对应的value
func main() { //内置的make函数可以创建一个map m := make(map[string]int) m["one"] = 1 m["two"] = 2 fmt.Println(m) // map[one:1 two:2] fmt.Println(len(m)) // 2 fmt.Println(m["one"]) // 1 fmt.Println(m["unknow"]) // 0 r, ok := m["unknow"] fmt.Println(r, ok) // 0 false delete(m, "one") m2 := map[string]int{"one": 1, "two": 2} var m3 = map[string]int{"one": 1, "two": 2} fmt.Println(m2, m3) }也可以用map字面值的语法创建map,同时还可以指定一些最初的key/value
ages := map[string]int{ "alice": 31, "charlie": 34, }但是map中的元素并不是一个变量,不能对map的元素进行取址操作(禁止对map元素取址的原因是map可能随着元素数量的增长而重新分配更大的内存空间,从而可能导致之前的地址无效)
_ = &ages["bob"] // compile error: cannot take address of map element
-
结构体
由零个或多个任意类型的值聚合成的实体。每个值称为结构体的成员
type user struct { name string password string } var u user当修改结构体的数据时,需要传入结构体的指针,进行修改
type user struct { name string password string } func (u user) checkPwd(password string) bool { return u.password == password } func (u *user) modifyPwd(password string) { u.password = password } func myPrint(flag bool) { if flag { println("比较成功") } else { println("比较失败") } } func main() { u := user{name: "hzy", password: "abc123"} flag := u.checkPwd("wakuwaku") myPrint(flag) u.modifyPwd("wakuwaku") println(u.password) } -
错误处理
通过
errors.New("xxx")创建新的错误func add(num1, num2 int) (res int, e error) { res = num1 + num2 return res, errors.New("错误") } func main(){ res, _ := add(1, 2) println(res) }