1.go语言申明一个变量:
- 最简单的方法
// var + 变量名 + type
var goVari type
- 自动赋于类型的懒人方法
// goVari 自动会定义成int类型
goVari := 2
var goVari int
goVari =2
// goVari 自动定义成string类型
goVari := "str"
- 我们也可以一次性申明多个变量
var goVari1, goVari2, goVari2 int
goVari1, goVari2, goVari2 = 1, 2, 3
//或者
var goVari1, goVari2, goVari2 = 1, 2, 3
goVari1, goVari2, goVari2 := 1, 2, 3
2.Go中数据类型
简单的数据类型
- 布尔型 bool
- 数字类型 int,float32,float64,complex64,complex128
- 字符串类型: string
派生类型
- 指针类型 Pointer
指针跟C++里面的指针是差不多的,首先我们要知道在go里面取地址符也是&,如果输出&goVari
就是输出这个变量的在内存中的地址。
那么指针就是用来指向一个值的内存地址,其实为什么Java里面没有指针,其实这个大家可以去看下Java的浅拷贝和深拷贝,一般而言,在Java中如果不是Clone的话,相同类型的变量赋值都是直接指向变量地址的,这样的话一个变量变化了,另一个变量也会变化,而指针就是这个作用。
var a int = 20
//申明一个可以指向int类型的指针
var ip *int
//ip指向a的内存地址,ip的地址=a的地址,ip要取值的话也是取a地址的值
ip = &a
a++
fmt.Printf(*ip, a)
// 21 21
- 数组类型
数组就比较简单了,但是相比Java中的数组,Go的数组不仅有静态数组,而且也沿用了C++中的动态数组,可以自动增加数组容量,这个类型被称为切片类型,在下面有讲到
//静态数组申明和调用
var goVari [3]int
//如果需要初始化
var goVari = [3]int{1,2,3}
goVari := [3]int{1,2,3}
//取值
goVari2 = goVari[0] // = 1
- 结构化类型 struct
//定义一个结构体
type book struct{
name string
author string
book_id int
}
func main(){
var book1 book
boook.name = "Go语言学习"
}
看到结构体,是不是有点像Java中的类,那么Java类中肯定不止变量了,还应该有很多方法,在Go中也是可以有方法的。
type iPhone struct{
price float32
color string
id string
}
//定义iPhone的方法
func (iphone iPhone) call(){
fmt.Println("This call is from %s", iphone.id)
}
//调用call函数
var iph iPhone
iph.call()
-
管道类型 chan 用于并发
-
切片类型 Slice
切片类型是对数组的抽象,可以被看作是动态数组,长度可以改变的数组,当然
//[]不定义长度来申明切片
var slice1 []int
slice1 := []int{1,2,3}
//通过make来定义切片, len为切片的初始长度
slice2 := make([]int,len)
- 接口类型 interface
Go的接口和Java的接口差不多的意思,申明几个方法,然后让其他函数去继承实现,这个可以配合struct类型来使用,因为struct本身是不能申明函数的,所以在外面申明的时候可以去实现某个接口
type phone interface{
call()
getname() string
getprice()(float32, float32, float32)
}
type HUAWEI struct{
name string
price_low float32
price_mid float32
price_high float32
}
func (huawei1 HUAWEI) call(){
fmt.Println("This call is from HUAWEI")
}
func (huawei1 HUAWEI) getname()string{
return huawei1.name
}
func (huawei1 HUAWEI) getprice()(float32, float32, float32){
return huawei1.price_low,huawei1.price_mid,huawei1.price_high
}
//当然如果我们有其他的struct也可以直接实现接口phone中的方法
//调用的时候
var huawei HUAWEI
...
huawei.getprice()
- Map类型
//map类型申明
var maps map[int]string //这个时候是nil的也就是空的,这个时候是不能放入键值对的,需要初始化
maps = make(map[int]string
//所以简化点就是
maps := make(map[int]string)
//map赋值
maps[1] = "go1"
maps[3] = "go2"
- range关键字
range关键字用于枚举数组或者其他类型中的每个元素
//枚举数组
num := []int{1,2,3}
// _ 表示num的下标,range会返回两个结果,index和num,这里_表示我们不需要index
for _, num := range nums
{
fmt.Println(num)
}
//枚举map
maps := map[string]string{"a":"apple","b":"banana"}
for k,v := range maps
{
fmt.Printf("%s -> %s", k, v)
}
3.Go的并发
很多地方从Java转go,有一部分原因是因为Go语言的高并发性能,所以了解go的并发实现也是很重要的。
Go中的并发都是通过goroutine关键字来支持的,goroutine是轻量级线程,其实他还有另外一个名字叫协程
,这些协程是Go高并发,高性能的前提条件。
goroutine
- 语法格式
//开启一个goroutine来执行func1
go func1(x,y,z)
- example:
func say(s string) {
for i := 0; i < 5; i++ {
time.Sleep(100 * time.Millisecond)
fmt.Println(s)
}
}
func main() {
go say("world")
go say("hello")
}
//output
world
hello
hello
world
world
hello
hello
world
world
hello
通道 channel
通道其实跟操作系统中的管道差不多,用来存储两个goroutine之间的通信数据,可以实现异步通讯,比如我routine1将数据先放入channel中,routine2并不一定是第一时间去channel取数据,而是可以在需要的时候再去取数据。
//申明一个channel,len可以设定通道的缓冲区大小
ch := make(chan int, len)
//放数据
ch <- v
//取数据,赋值给getData
getData := <- ch
// range关键字遍历通道
for i := range ch{
fmt.Printf(i)
}