golang基础语法(一)|青训营笔记

123 阅读4分钟

这是我参与「第三届青训营 -后端场」笔记创作活动的的第一篇笔记

1.golang内置变量类型

  • bool, string;
  • (u)int, (u)int8, (u)int16, (u)int32, (u)int64, uintptr;
  • byte, rune
  • float32, float64, complex64, complex128. 其中(u)int的位数由操作系统决定; uintptr是指针;
    byte和rune是int的别名,byte是8位rune是32位;
    complex64的实部和虚部都是float32,complex128的实部和虚部都是float64。
    go没有隐式类型转换,都要做显示的强制转换。

2.变量定义方式

方式一:使用var定义

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

输出

fmt.Println(a, b, c, d, e, f) // initial 1 2 true 0 0
fmt.Println(g)                // initialapple
fmt.Println(s, h, i)          //constant 500000000 6e+11 

3.条件语句

  • if 后的条件判断不需要加括号
  • if 后的大括号不能省略(即使只有一条执行语句)
  • if 后面可以定义变量
if 7%2 == 0 {
   fmt.Println("7 is even")
} else {
   fmt.Println("7 is odd")
}

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 后的变量名不需要括号
  • switch 中不用写break
  • switch 后可以不加任何变量,直接在每个 case 处加判断语句
a := 2
switch a {
case 1:
   fmt.Println("one")
case 2:
   fmt.Println("two")
case 3, 4:
   fmt.Println("three or four")
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")
}

4.循环语句

golang里没有while,do while循环,只有一种for循环

i := 1
for {                     // 不写条件就是死循环
   fmt.Println("loop")
   break
}

for n := 0; n < 5; n++ {
   if n%2 == 0 {
      continue
   }
   fmt.Println(n)
}
for i <= 3 {
   fmt.Println(i)
   i = i + 1
}

5.数组

定义方式:

var a [5]int
a[4] = 100
fmt.Println("get:", a[2])
fmt.Println("len:", len(a))

b := [5]int{1, 2, 3, 4, 5}
fmt.Println(b)

var twoD [2][3]int
for i := 0; i < 2; i++ {
   for j := 0; j < 3; j++ {
      twoD[i][j] = i + j
   }
}
fmt.Println("2d: ", twoD)

数组的长度是固定的,实际开发很少用,一般用切片slice

6.slice 切片(可变长度数组)

用 make 创建切片,用 append 扩充切片(对原数组)

slice本身没有数据,是对底层array的一个view
slice的内部:
ptr,指向slice开头的元素,
len,说明slice的长度,方括号取值时只能取到length里面的值,下标超出就报错,
cap(capacity:容量),从ptr开始到结束的整个array的长度;

扩展时,只要不超过capacity就可以扩展,只能向后扩展;
cap(s):slice的容量, len(s):slice的长度

添加元素时如果超过cap,系统会重新分配更大的底层数组
由于是值传递,必须有参数接收append的返回值
s = append(s, val)

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]

7.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"]     // ok 可以用来判断value存不存在(golang 函数可以有多个返回值)
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)

8.range

对于任意 slice 和 map 可以用 range 来遍历
定义两个变量代表返回索引和值(key和value),省略变量可以用_代替

nums := []int{2, 3, 4}
sum := 0
for i, num := range nums {
   sum += num
   if num == 2 {
      fmt.Println("index:", i, "num:", num) // index: 0 num: 2
   }
}
fmt.Println(sum) // 9

m := map[string]string{"a": "A", "b": "B"}
for k, v := range m {
   fmt.Println(k, v) // b 8; a A
}
for k := range m {
   fmt.Println("key", k) // key a; key b
}

9.函数

golang 中函数返回值类型放在后面
函数可以作为参数传递,没有默认参数,可选参数,有变长参数
函数可以返回多个值,可以为返回的多个值起名字

func add(a int, b int) int {
   return a + b
}
func add2(a, b int) int {
   return a + b
}
func exists(m map[string]string, k string) (v string, ok bool) {
   v, ok = m[k]
   return v, ok
}

func main() {
   res := add(1, 2)
   fmt.Println(res) // 3

   v, ok := exists(map[string]string{"a": "A"}, "a")
   fmt.Println(v, ok) // A True
}

10.指针

golang 中指针的作用非常有限,主要是对原数据修改

func add2(n int) {
   n += 2
}
func add2ptr(n *int) {
   *n += 2
}

func main() {
   n := 5
   add2(n)
   fmt.Println(n) // 5
   add2ptr(&n)
   fmt.Println(n) // 7
}

11.结构体

具体使用如代码所示

type user struct {
   name     string
   password string
}

func main() {
   a := user{name: "wang", password: "1024"}
   b := user{"wang", "1024"}
   c := user{name: "wang"}
   c.password = "1024"
   var d user
   d.name = "wang"
   d.password = "1024"

   fmt.Println(a, b, c, d)                 // {wang 1024} {wang 1024} {wang 1024} {wang 1024}
   fmt.Println(checkPassword(a, "haha"))   // false
   fmt.Println(checkPassword2(&a, "haha")) // false
}

func checkPassword(u user, password string) bool {
   return u.password == password
}
func checkPassword2(u *user, password string) bool {
   return u.password == password
}

12.结构体方法

为结构体定义方法,可以将普通函数变为类成员函数
具体见代码(注意与上方结构体普通函数进行比较)

type user struct {
   name     string
   password string
}

func (u user) checkPassword(password string) bool {
   return u.password == password
}
func (u *user) resetPassword(password string) {
   u.password = password
}

func main() {
   a := user{name: "wang", password: "1024"}
   a.resetPassword("2048")
   fmt.Println(a.checkPassword("2048")) // true
}