Go 基础语法

115 阅读3分钟

Hello World

语法真的很简洁,Go 的包中的方法大多是大坨峰写法。

package main  
  
import (  
"fmt"  
)  
  
// 1. 运行:go rn example/01-hello/main.go  
// 2. 编译为二进制:go build example/01-hello/main.go  
// 执行二进制文件:./main  
func main() {  
    fmt.Println("hello world")  
}

变量和常量

变量

声明变量有两种写法

  1. 使用 var
// 直接赋值,等价于 var a string = "initial"  
var a string = "initial"  
  
// 声明类型,但其实 var 会根据值自动推断类型  
var b, c int = 1, 2  
  
// 直接赋值,等价于 var d bool = true  
var d = true  
  
// 如果不赋值,则需要声明类型,因为没有值,所以不能自动推断类型  
var e float64
  1. 使用 :=
// 使用 := 代替 var,两种等价,推荐使用第一种  
f := float32(e)  
var f2 = float32(e)  // 注意,Go 中如果声明了变量不使用会报错  
  
g := a + "foo"  
fmt.Println(a, b, c, d, e, f) // initial 1 2 true 0 0  
fmt.Println(g) // initialapple

常量(后续增加内容)

常量使用 const,和 C/C++ 中一样。Go 中的常量没有固定类型,自动确定类型

const s string = "constant"  
const h = 500000000  
const i = 3e20 / h  
fmt.Println(s, h, i, math.Sin(h), math.Sin(i))

for、if、switch

for

Go 中没有 while,相当炸裂!使用下面的 for 代替 while

for {  
    fmt.Println("loop")  
    break  
}

for 不写括号,j 是新定义的变量,因此使用 :=,当然也可以使用 var j = 7,但 := 更简洁

for j := 7; j < 9; j++ {  
    fmt.Println(j)  
}
for i <= 3 {  
    fmt.Println(i)  
    i = i + 1  
}  
for ; i <= 3; i++ {  
    fmt.Println(i)  
}

if

if 也是没有括号,而且可以先赋值,再判断,一行搞定,优雅!对了,当 fmt.Println() 中有多个参数时,默认会按空格隔开

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 中不用写 Java、C/C++ 中的 break,a 可以是任意值,包括结构体,还可以写成 2, 3 这样的列表

a := 2  
switch a {  
case 1:  
    fmt.Println("one")  
case 2, 3:  
    fmt.Println("two or three")  
default:  
    fmt.Println("other")  
}

数组(固定大小)和切片(可扩容,常用)

数组

数组的声明看着有些不习惯,用惯了 Java 的 int[] nums = new int[10]

// 一维数组
var a [5]int  
a[4] = 100

b := [5]int{1, 2, 3, 4, 5}

// 二维数组
var twoD [2][3]int

切片

这个切片类似 Java 中的 List,注意添加元素的写法,需要重新赋值给 s,因为数组扩容了,开了一个新的数组,s 中这个新数组,可以在参数中添加多个元素,太简洁了。

s := make([]string, 2)  
s[0] = "a"  
s[1] = "b"

s = append(s, "d")  
s = append(s, "e", "f")

数组的深拷贝

c := make([]string, len(s))  
copy(c, s)  
fmt.Println(c) // [a b c d e f]

切片数组可以切片,类似于 Python。但是不能负数

fmt.Println(s[2:5]) // [c d e]  
fmt.Println(s[:5]) // [a b c d e],不包括下标 5

map

map 的声明方式也是相当炸裂,不过确实简洁。注意使用了 make,和前面的切片一样。map 的访问方式和 C/C++ 中一样,是数组的访问方式。注意,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["unknown"]) // 0

判断 map 中是否存在某个 key。ok = 1 表示存在,ok = 0 表示不存在

r, ok := m["unknown"]  
fmt.Println(r, ok) // 0 false

删除 key

delete(m, "one")

直接创建 map

m2 := map[string]int{"one": 1, "two": 2}  
var m3 = map[string]int{"one": 1, "two": 2}  
fmt.Println(m2, m3)

遍历数组、map

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  
}