这是我参与「第三届青训营 -后端场」笔记创作活动的第1篇笔记
go语言的特点
Go 具有表现力、简洁、干净和高效。它的并发机制使编写充分利用多核和联网机器的程序变得容易,而其新颖的类型系统支持灵活和模块化的程序构建。
Go语言的主要特征:
- 1.自动立即回收
- 2.更丰富的内置类型
- 3.函数多返回值。
基本语法
hello World
package main
import (
"fmt"
)
func main() {
fmt.Println("hello world")
}
- 第一行package main代表这个文件属于main包的一部分,main包也就是程序的入口包。 第三行导入了标准库里面的FMT包。这个包主要是用来往屏幕输入输出字符串、格式化字符串。 import 下面是main函数,main函数里面调用了fmt.Println 输出helloword
var 关键字
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))
}
- 使用 var 关键字是Go最基本的定义变量方式,有时也会使用到 := 来定义变量。
- 操作符 := 快速变量声明。可以同时声明并初始化一个变量,不必声明一个具体类型的变量,Go语言可以从其初始化值推导其类型。
- 变量e没有显示初始化,会赋零值,字符串会默认为空。
- Go语言中的常量使用关键字 const 定义,用于存储不会改变的数据,常量是在编译时被创建的。
- Go语言提供了大量内置的数值类型。不能在不同的类型之间进行二进制数值运算或比较操作。
- 3e20是科学计数法 3*10^20
- Math.Sin(x) 以弧度为单位的x的正弦值
if语句
import "fmt"
func main(){
if 7%2==0 {
fmt.Println("7 is even")
}else {
fmt.Println("7 is odd")
}
//if optionalStatement1;booleanExpression1 {}
if num:=8;num<0 {
fmt.Println(num,"is negetive")
}else if num<10{
fmt.Println(num,"has 1 digit")
}
}
- if语句的大括号是强制性的,条件判断中的分号只有在可选语句optionalStatement出现的情况下需要。
- 第一个if语句的num变量扩展到了if...elseif...语句中,因此他们在每一个分支中都是可见的。
for循环
package main
import "fmt"
func main(){
i:=1
//for booleanExpression{block}
for{
fmt.Println("loop")
break
}
// for optionalPreStatement;booleanExpress;optionalPostStatement
for j:=7;j<9;j++{
fmt.Println(j)
}
for n:=9;n<5;n++ {
if n%2==0 {
continue
}
fmt.Println(n)
}
for i<=3 {
fmt.Println(i)
i=i+1
}
}
- Go 语言的for循环有3种形式,只有其中的一种使用分号。
switch循环
import (
"fmt"
"time"
)
func main(){
a := 2
//switch optionalStatement{
switch a {
//case expressionList1:
//block
case 1:
fmt.Println("one")
case 2:
fmt.Println("two")
case 3:
fmt.Println("three")
//default:bloakD
default:
fmt.Println("other")
}
t:=time.Now()
switch {
case t.Hour()<12:
fmt.Println("1")
default:
fmt.Println("2")
}
}
- 不同于c和java,go的switch语句不会自动向下贯穿,因此不必在每个case字句末尾添加break语句,需要case语句向下贯穿时可以显式调用fallthrough
- 没有可选的表达式语句,编译器会把表达式语句设为true。意味着case语句的每一个表达式都必须计算为布尔类型。
range
package main
import "fmt"
func main() {
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
}
}
- 对于一个slice或者一 个map的话,可以用range来快速遍历,可以使代码更加简洁。range遍历的时候,对于数组会返回两个值,第一 个是索引,第二个是对应位置的值。如果我们不需要索引的话,我们可以用下划线来忽略。
切片
import "fmt"
func main(){
s:=make([]string,3)
s[0]="a"
s[1]="b"
s[2]="c"
fmt.Println("get:",s[2])
fmt.Println("len:",len(s))
s=append(s,"d")
s=append(s,"e","f")
//[a b c d e f]
fmt.Println(s)
c:=make([]string,len(s))
copy(c,s)
//[a b c d e f]
fmt.Println(c)
//[c d e]
fmt.Println(s[2:5])
// [a b c d e]
fmt.Println(s[:5])
//[c d e f]
fmt.Println(s[2:])
good := []string{"g","o","o","d"}
fmt.Println(good)
}
- 切片不同于数组可以任意更改长度,然后也有更多丰富的操作。比如说我们可以用make来创建一个切片, 可以像数组-样去取值,使用append来追加元素。
- 注意append的用法的话,你必须把append的结果赋值为原数组。
- 因为slice的原理实际上是它有一个它存储了一个长度和一个容量,加一个指向一个数组的指针,在你执行append操作的时候,如果容量不够的话,会扩容并且返回新的slice。
- slice此初始化的时候也可以指定长度。
- slice拥有像python一样的切片操作,比如这个代表取出第二个到第五个位置的元素, 不包括第五个元素。不过不同于python,这里不支持负数索引。
map
import "fmt"
func main(){
m:=make(map[string]int)
m["one"]=1
m["two"]=2
//map[one:1 two:2]
fmt.Println(m)
//2
fmt.Println(len(m))
//1
fmt.Println(m["one"])
//0
fmt.Println(m["unknow"])
r,ok := m["unknow"]
//0 false
fmt.Println(r,ok)
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是实际使用过程中最频繁用到的数据结构。
- 我们可以用make来创建一个空map,这里会需要两个类型,第一个是那个key的类型,这里是string另一个是value的类型这里是int。 我们可以从里面去存储或者取出键值对。可以用delete从里面删除键值对。
- golang的map是完全无序的,遍历的时候不会按照字母顺序,也不会按照插入顺序输出,而是随机顺序。
结构体
import (
"fmt"
)
type user struct{
name string
password string
}
func main(){
a := user{name:"li",password:"1024"}
b := user{"li","1024"}
c :=user{name:"li"}
c.password="1024"
var d user
d.name="wang"
d.password="1024"
fmt.Println(a,b,c,d)
//false
fmt.Println(checkPassword(a,"haha"))
//false
fmt.Println(checkPassword2(&a,"haha"))
a.resetPassword("2048")
//true
fmt.Println(a.checkPassword("2048"))
}
func checkPassword(u user,password string) bool{
return u.password==password
}
func checkPassword2(u *user,password string) bool {
return u.password==password
}
func (u *user)resetPassword(password string){
u.password=password
}
func (u user)checkPassword(password string)bool{
return u.password==password
}
- 结构体是一种聚合的数据类型
- 结构体定义需要使用 type 和 struct 语句。struct 语句定义一个新的数据类型,结构体中有一个或多个成员。type 语句设定了结构体的名称。
函数
import "fmt"
func add(a int,b int)int {
return a+b
}
func add2(a,b int) int{
return a+b
}
func add3(n int){
n+=2
}
func add3ptr(n *int){
*n+=2
}
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)
v,ok:=exists(map[string]string{"a":"A"},"a")
fmt.Println(v,ok)
n:=5
add3(n)
fmt.Println(n)//5
add3ptr(&n)
fmt.Println(n)//7
}
- Golang 和其他很多语言不-样的是,变量类型是后置的。
- Golang里面的函数原生支持返回多个值。在实际的业务逻辑代码里面几乎所有的函数都返回两个值,第一个是真正的返回结果,第二二个值是一个错误信息。