目录
代码基本结构
变量
选择结构
循环结构
数组与切片
字典
函数
本篇文章主要介绍了Go语言的一些基础语法,概括性地介绍这几天自己的所学所悟。主要从上述七个方面进行介绍,希望能帮助大家迅速了解Go的基础语法。
内容主要总结于
- 字节跳动青训营——GO语言原理与实践
- Go语言圣经
代码基本结构
在上手go语言之前,先引入基本的代码——输出“Hello World!”
package main
import "fmt"
func main(){
fmt.Println("Hello World!")
}
代码主要分为三部分,第一部分package,go中所有文件都需要指定对应的包,包有main和非main两种类型,其中只有main包能够转化为可执行文件;第二部分import,import用该方法导入对应包;第三部分为主函数,通过它输出Hello World!
变量
go语言常用的变量声明方式有两种,如下所示
var b, c int = 1, 2
var e float64
f := float32(e)
可以用var name int=1 这样的方式声明整型变量,也可以用name:=这一方式声明变量,需要注意的是这里跟c直接类型+变量名和变量名=赋值的声明方式的区别。
而对于常量,则是把上述的var改为const,如下所示。
const s string = "constant"
const h = 50000000
这里不同的一个地方是,go中的const可以不用定义具体的类型,go语言会根据上下文自行确定相应的类型。
选择结构
go中的选择结构跟C和C++大差不差,也是使用if-else进行处理,直接上代码进行分析。
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")
}
}
这里的if和else后面跟着的语句都不用加括号,这是与C不同的地方,在下面if-else if-else的分支中,我们可以看出不同于C要完整地写出else if的条件,go的else if条件是在第一个if的反条件的基础上再加限制的,因此上述代码中的else if条件实际上是等同于if num>=0&&num<10.
go还有一种分支结构——switch,go与C的switch很大一个不同在于,C中的switch每一个case都要加入一个break,否则会出错;而go中的switch不需要,他执行到对应条件完毕后即会停止。如代码所示。
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")
}
在这段代码中,输出的结果是two,而执行完毕后程序自动跳出循环。
switch还有个不同之处在于可以在case分支中加入条件,且无需考虑变量,这样相比于C和C++中用if-else要清楚的多,直接上代码。
t := time.Now()
switch {
case t.Hour() < 12:
fmt.Println("It's before noon")
default:
fmt.Println("It's after noon")
}
当前时间在12点前则输出前半段,反之则后半段。
循环结构
相比于C和C++中的三种循环结构do-while、while和for,go语言大幅度精简了循环结构,在go中只有一种for循环,最简单的是单独for,没有任何其他条件代表死循环,可以用break跳出,也可以用类似于C和C++中的三段条件那样限制,在循环中可以用break和continue来跳出或者继续循环。代码如下。
i := 1
for {
fmt.Println("loop")
break
}//loop
for n := 0; n < 5; n++ {
if n%2 == 0 {
continue
}
fmt.Println(n)
} //1、3
数组与切片
关于数组方面不多赘述,直接上代码。
var b [5]int
c := [5]int{1, 2, 3, 4, 5}
与C和C++有所不同的地方,在于定义数组的方式不同,相比于C和C++有些“繁琐”,前者代表定义一个数组b,长度为5;后者则是定义一个数组c,其中元素为1-5。在实际使用中,数组由于是固定长度,故而常用的是切片——slice
slice主要用到make进行创建,语法为make([]类型,长度),可以创建一个切片,切片的操作主要有:可以像数组一样进行索引,还有可以类似于python进行切片操作,但不能用负数进行索引。上代码。
s := make([]string, 3) //make创造切片
s[0] = "a"
s[1] = "b"
s[2] = "c"
fmt.Println("get:", s[2]) //c
fmt.Println("len:", len(s)) //3
copy(c, s) //把s切片复制到c
fmt.Println(s[2:5])
fmt.Println(s[:5])
fmt.Println(s[2:])
切片这里还有一些相对于数组方便的操作,相比于python中的list操作,go的slice含有append和copy,但其他python中的list操作许多都要自己实现。这也是go的一个不足之处。
s := make([]string, 3) //make创造切片
s = append(s, "d")
s = append(s, "e", "f")
copy(c, s) //把s切片复制到c
字典
在go中,字典map通过make进行创建,第一个是属于索引(key),第二个是对应的值(value),可以通过key取出值,也可以通过delete删除键值对。go中的map是完全无序的,遍历时是按照随机顺序的。
func main() { //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
delete(m, "one")
m2 := map[string]int{"one": 1, "two": 2}
var m3 = map[string]int{"one": 1, "two": 2}
fmt.Println(m2, m3)
}
函数
函数这块没啥好说的,注意下跟很多语言不同的地方就是变量类型后置(感觉就是为了区别不同语言刻意后置的,真的挺蹩脚的)。上下示例代码,这个的输出结果是7.
package main
import (
"fmt"
)
func add2ptr(n *int) {
*n += 2
}
func main() {
n := 5
add2ptr(&n)
fmt.Println(n)
}
错误处理
这里直接上代码进行分析,更容易看一些,在go中错误处理常与函数进行连用,第一个返回一个处理结果,第二个则是返回一个错误信息。
package main
import (
"errors"
"fmt"
)
type user struct {
name string
password string
}
func findUser(users []user, name string) (v *user, err error) {
for _, u := range users {
if u.name == name {
return &u, nil
}
}
return nil, errors.New("not found")
}
func main() {
u, err := findUser([]user{{"wang", "1024"}}, "wang")
if err != nil {
fmt.Println(err)
return
}
fmt.Println(u.name)
if u, err := findUser([]user{{"wang", "1024"}}, "li"); err != nil {
fmt.Println(err)
return
} else {
fmt.Println(u.name)
}
}
go语言能够很容易地知道哪里出错,在实际应用中,如果不出现错误则返回原本结果和一个空nil,如果出错,则返回对应错误的输出。例如在上述例子中,会分别输出wang和not found.
大概关于基础语法的整理就到这里,也算是对自己最近学习的一个整理。