Go(又称 Golang)是 Google 的 Robert Griesemer,Rob Pike 及 Ken Thompson 开发的一种静态强类型、编译型语言。Go 语言语法与 C 相近,但功能上有:内存安全,GC(垃圾回收),结构形态及 CSP-style 并发计算。
import (."fmt")
//之后调用这个包函数时,可以省略前缀包名
Println("hello world")
import (f"fmt")
f.Println("hello world")
//变量声明
//1.指定变量类型,声明后不赋值
var a int
a=12
//2.根据值自动推导变量类型
var b=12
//3.使用:=直接取代var关键字和变量类型
c:=10
//4.多变量声明中用于声明全局变量的写法
var (
vname1 v_type1
vname2 v_type2
)
//匿名变量:_(下划线)是特殊的变量名,任何赋予的值都会被丢弃
_ ,b := 34,35
iota是一个常量计数器,可以认为是一个被编译器修改的常量,每个const关键字出现时被重置为0,然后在下一个const出现前,每出现一次iota,其代表的数字会自动加1,可以用于枚举。
package main
import "fmt"
func main(){
const(
a=iota
b
c
)
fmt.Println(a,b,c)
}
//输出0 1 2
package main
import "fmt"
func main(){
var v1 complex64
v1=3.2+12i
v2 :=3.2+12i
v3:=complex(3.2,12)
//获取实部和虚部
fmt.Println(real(v1),imag(v1))
}
package main
import "fmt"
type text string
func main(){
var t text = "hello world"
fmt.Println(t)
}
package main
import("fmt")
func main(){
if a:=3;a==3{
fmt.Println("a==3")
}
}
//声明与初始化
array1 :=[5] int{10,20,30,40,50}
array2 :=[...]int{10,20,30}
//初始化索引为1和2的元素
array3 :=[5]int{1:10,2:20}
//for...range遍历数组元素
package main
import("fmt")
func main(){
var a[2]int
a[0]=10
a[1]=12
for i,v:=range a{
fmt.Println("Array element[", i, "]=",v)
}
}
在go语言中数组是一个值类型,在函数体中无法修改传入的数组的内容。
//创建一个初始元素个数为5的数组切片,元素初始值为0,并预留10个元素的存储空间。
mySlice := make([]int,5,10)
myslice1 :=[]int{1,2,3,4,5}
//映射例子
inf :=map[int]string{
110:"警察局",
114:"查号中心",
119:"消防局",
120:"急救中心"
}
字符串可以使用双引号“”定义,也能使用反引号’'定义。反引号最大的好处是支持跨行操作。
较少字符串连接的场景下直接使用加号运算符会使代码简短清晰,可读性好。
str1:="abcd"
str2:="efg"
str=str1+str2
如果需要拼接的不仅仅是字符串,还有数字之类的其他需求的话,可以考虑fmt.Sprintln()函数。
str1:="abcd"
str2:="efg"
str:=fmt.Sprintln("%s%s",str1,str2)
在已有字符串数组的场合,使用strings.Join()函数有比较好的性能。
//需要import("strings")
str:=[]string{"ab","cd","ef"}
str:=strings.Join(str,"")
在一些性能要求较高的场合,尽量使用buffer.WriteString()函数以获得更好的性能。
//需要import("bytes")
var buf bytes.Buffer
buf.WriteString("abcd")
buf.WriteString("efg")
//输出buf.String()
这种方式比较理想,可以当作一个可变长字符串来使用,对内存的增长也有优化。如果能够预估字符串的长度,还可以用buffer.Grow()设置缓存容量。
除了“先将字符串转成 []rune切片,然后用常规方式遍历”方法外,还有其他三种方法。
copy函数将第二个切片的元素复制到第一个切片中,复制长度为两切片中长度较小的那个。
//声明指针
package main
import("fmt")
func main(){
var ptrA *int
var ptrB = new(float32)
var c float64
ptrC := &c
//分别为0,指针b,指针c
//即未被初始化的指针为nil
}
Go语言指针不同于C/C++地方:不能在程序中对指针的值进行运算,即不支持指针的自增、偏移等。
但是它也为Go语言的垃圾回收机制提供了便利,不会因为垃圾回收而悬空指针。
不支持"—>"运算符,直接用"."访问目标成员。
数组元素全为指针的数组称为指针数组。数组指针是指只想数组首元素的地址的指针,其本质为指针;指针数组是数组元素为指针的数组,其本质为数组。
区分数组指针和指针数组的方法:看"
*
"和谁结合。
如p *[5] int
,*
与数组结合说明是数组的指针;如p [5] *int
,*
与int结合,说明数组都是int类型的指针,是指针数组。
type Student struct{
ID int
Name string
Address string
Age int
Class string
Teacher string
}
var lm Student
//结构体的初始化
//第一种格式:顺序为每个成员变量指定一个值
type Point struct{X,Y int}
p:=Point{1,2}
// 第二种格式:指定部分或者全部成员变量的名称和值来初始化结构体变量,如果成员被忽略,默认用零值
lm := Student{ID:2021201}
type Person struct{}
type Ptr *Person
func (p Ptr) getName(){} //编译错误
func (p Person) getName(){}
func (p *Person)getName(){}
接口是一系列方法的集合。接口定义了一组方法,但这些方法不包含代码,它们并不在接口中实现。
type Any interface{}
func funcA(args...interface{}) interface{}{
}
空接口被称为"最小接口",没有任何方法,实现他们不需要满足任何要求。一个空接口变量可以被任意赋值,从而指向任何类型的对象。
最典型的例子是fmt库中的输出函数,通过配合空接口和类型查询,能够实现可接受任意对象实例并进行处理的函数。
一个接口变量所包含的值的类型有多种可能,为了动态判断接口代表的实际类型,需要利用Go语言的类型断言机制。
//检查变量varI是否是TypeA类型,判断并赋值
varC , ok := varI.(TypeA)
//类型查询
switch varC := varI.(type){
case int:
carC++
case string:
varC = "It's a string"
...
default:
...
}