有个疑问,的主题还有代码款式里哪个是支撑显现代码行号的?然后为啥这儿代码段一个 Tab 给我渲染了八个空格。

这次是语法专题,仍是分开发,全都放一篇我自己复习的时分压力太大了。

Go 的变量类型

来个小比如:

package main
import (
	"fmt"
	"math"
)
func main() {
	var a = "initial"
	var b, c int = 1, 2
	var d = true
	var e float64
	f := float32(e)
	g := a + "foo"
	fmt.Println(a, b, c, d, e, f) // initial 1 2 true 0 0
	fmt.Println(g)                // initialapple
	const s string = "constant"
	const h = 500000000
	const i = 3e20 / h
	fmt.Println(s, h, i, math.Sin(h), math.Sin(i))
}

Go 也是强类型言语,在声明的时分有两种方法,第一种是 var name = value,这种状况下一般是依据给变量名赋的值自动推导变量类型,当然也能够显式的写出来变量类型。声明的时分不一定要初始化,所以规则好变量类型是有必要的。第二种方法是 name := value。声明时,变量的默许类型是:boolruneintfloat64complex128string 这些。

常量的声明便是把 var 改成 const,常量的类型依据上下文自动确认。

运转成果:

initial 1 2 true 0 0
initialfoo
constant 500000000 6e+11 -0.28470407323754404 0.7591864109375384

改一下带入正弦函数的输入,能够测试出来默许是弧度制。

Go 的 if 和 else

来个小比如:

package main
import "fmt"
func main() {
	if 7%2 == 0 {
		fmt.Println("7 is even")
	} else {
		fmt.Println("7 is odd")
	}
	if 8%4 == 0 {
		fmt.Println("8 is divisible by 4")
	}
	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")
	}
}

ifelseC 里边的类似,可是后边接的条件句子没有括号包住。如果顺手就把括号写上了,保存文件的时分编辑器会把括号去掉。然后条件句子那个代码块必须用大括号包起来,不能像 c 或者 C++ 相同只要一行代码就不写大括号了。

运转成果如下:

7 is odd
8 is divisible by 4
9 has 1 digit

Go 的循环

来个小比如:

package main
import "fmt"
func main() {
	i := 1
	for {
		fmt.Println("loop")
		break
	}
	for j := 7; j < 9; j++ {
		fmt.Println(j)
	}
	for n := 0; n < 5; n++ {
		if n%2 == 0 {
			continue
		}
		fmt.Println(n)
	}
	for i <= 3 {
		fmt.Println(i)
		i = i + 1
	}
}

Go 只要 for 循环,其他的循环语法没有。啥条件都不写便是死循环,然后经典的 C 风格 for 循环,仍是没有小括号把条件包住。分三段的条件能够省略其间任何一段,也不必写分号表示某一段被省略了,continue 持续循环和 break 跳出循环仍是相同的。

运转成果如下:

loop
7
8
1
3
1
2
3

Go 的 switch

来个小比如:

package main
import (
	"fmt"
	"time"
)
func main() {
	a := 2
	switch a {
	case 1:
		fmt.Println("one")
	case 2:
		fmt.Println("two")
	case 3:
		fmt.Println("three")
	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")
	}
}

C 类似的语法,条件变量不必小括号包上,每个状况完毕今后不需求显式的写上 break,一个状况履行完也不会持续把下面的状况全部履行一遍,直接就跳出来了。Goswitch 能够把字符串,结构体当条件变量,还能够取代 if ... else ... 的嵌套,比如里边就有一个 switch 没加任何条件变量直接拿每个 case 来当 if ... else ... 写的。

运转成果:

two
It's after noon

我记得曾经有个技巧是用卫句子改善条件分支嵌套,不知道这个技巧在 Go 代码里边是怎么实践的。

Go 的数组

来个小比如:

package main
import "fmt"
func main() {
	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)
}

数组长度固定,空间开大了糟蹋开少了又要扩容,然后本来数组的内容要一个一个搬到新的数组里,麻烦,实在的事务代码里不是很常用,之后的切片才是更常用的。

运转成果:

get: 0
len: 5
[1 2 3 4 5]
2d:  [[0 1 2] [1 2 3]]

不过 Go 某些方面仍是更便利一些,二维数组直接就打印出来了。

Go 的切片

来个小比如:

package main
import "fmt"
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]
}

切片是可变长度的数组,用 make() 来创立切片。创立的时分要规则元素的数据类型以及长度。用 append() 交游切片后边添加新元素。在添加新元素的时分 append() 之后的成果是要重新赋给原切片变量的,由于 slice 底层原理是开一个长度预设容量计算好的数组和一个指向数组的指针,append() 操作之后本来的 slice 容量不行,扩容今后是一个新的 slice,所以赋值操作是必须的。copy() 用来在两个 slice 之间拷贝数据。

都叫切片了,这个数据结构也和 Python 里边同名的数据结构相同有便利的切片操作,可是不支撑负数索引,所以仍是需求一些数学运算。