golang变量定义、数据类型、可见性

golang中主要基础数据类型如下:

类型 描述
uint8 无符号 1个字节8位整型 (0 到 255)
uint16 无符号 2字节16位整型 (0 到 65535)
uint32 无符号 4字节32位整型 (0 到 4294967295)
uint64 无符号 8字节64位整型 (0 到 18446744073709551615)
int8 有符号 1字节8位整型 (-128 到 127)
int16 有符号 2字节16位整型 (-32768 到 32767)
int32 有符号 4字节32位整型 (-2147483648 到 2147483647)
int64 有符号 8字节64位整型 (-9223372036854775808 到 9223372036854775807)
uint 32位操作系统上就是uint32,64位操作系统上就是uint64
int 32位操作系统上就是int32,64位操作系统上就是int64
float32 32 位浮点型
float64 64 位浮点型
complex64 32 位实数和虚数
complex128 64 位实数和虚数
uintptr 无符号整型,用于存放一个指针
bool 1字节8位,只允许 true和false不能转int,默认值为false
string 默认值为 “”

变量定义

golang中可以通过如下几种方式对变量进行定义:

  1. var name type 方式,这种情况下,变量的值为其零值,比如:
var a int;
var b int = 3

如果指定了其初始值,那么不用指定类型,形如: var name = value 格式,如:

var a = 100
  1. name : = value 格式,这种只能在函数内部用,使用 := ,golang会自动推导其类型
a := 100
  1. 一次定义多个变量,按照从左到右的方式赋值:
var a, b, c int
var a, b, c int = 1,2,3
var a, b, c  = 1,2,3

a,b,c := 1,2,3 // 必须在方法内部使用
  1. 使用var () 一次定义多个:
var (
    a int 
    b string
    c []float32
    ...
)

数组

golang中数组声明如下:
var name [size]type 如:

var arr [2]int

声明了一个长度为2类型为int的数组,数组中的每个元素初始值都为0
或者:

arr := [...]int{1,2,3,4}
brr := [3]int{1,2,3}

切片

golang中切片声明如下:
var name []type如:

var sli []int

还可以通过如下方式:

var slicea []int = arr[0:1] //  arr[:]复制所有
sliceb := make([]int,5,5)

指针

我们知道golang中很多函数都是基于值传递的,需要进行复制,如果对象比较大,那么比较耗时,这时候我们可以使用指针,指针对应的内存中存储的是实际变量的地址,这样当我们进行函数调用传递指针(也是值复制,但是这里复制的是一个指针),我们就不用复制整个数据类型,而只用复制指针即可,然后通过指针能够对原有对象进行访问。
一般指针生命如下:

var pName *type

指针类型与一般类型的最大区别就是增加了一个*来表明这是一个指针类型。而指针类型进行初始化则需要配合取地址运算符&:

var age int = 20;
var pAge *int =&age;

访问指针内容,也是使用*:

var age int =20
var pAge *int = &age
*pAge = 30
fmt.Print(age)

通道

golang中通道主要是用来goroutine之间用进行通信的工具,通道一般可以声明如下:

var chanName chan type

比如:

var message chan int;
message = make(chan int)

通过到通过make进行初始化
向通道发送数据通过<-进行发送:

var message chan int;
message = make(chan int)
message <- 20

接收通道数据同样使用操作符<-

data := <- message

如果我们想要忽略接收数据,则可以如下操作:

<- message

data := <- message执行时,如果没有数据,则会阻塞,完整写法如下:

data,ok := <- messag

ok为bool类型,通过ok可以判断通道是否被关闭。
另外,如果没有接收到数据,则data默认为data类型的零值
如果需要循环接收数据,则可以通过for循环和for range进行循环接收数据:

// example 1
	for {
		data := <- message
		if data == 0 {
			break
		}
		fmt.Println("receive data from chan: ",data)
	}

	// example 2
	for {
		data,ok := <- message
		if !ok {
			fmt.Println("chan is closed")
			break
		}
		fmt.Println("receive data from chan: ",data)
	}

	// example 3
	for data := range message {
		fmt.Println("receive data from chan: ",data)
	}

这其中for range方式能够自动判断通道是否关闭
需要注意的是通道默认是阻塞的,当数据发送到通道中通道发生阻塞知道其他goroutine从通道中读取数据。当从通道中读取数据时也会被阻塞知道其他goroutine将数据写入到该通道中,通过这种机制,通道能够帮助goroutine实现类似锁的机制

默认创建通道的方式是不带有缓冲区的,读写都是即时阻塞。我们可以创建带有缓冲区的通道,这样当缓冲区未满时,读写都是非阻塞的,创建缓冲通道示例如下:

var message chan int;
message = make(chan int,10)

默认通道都是双向的,可读可写,我们也可以指定通道的方向也就是通道的读写性,一般这种特性主要是用于函数的参数,确保在函数内只能读取或者写入数据到通道中

//读通道
var readChan  <- chan int
readChan = make(<- chan int)

//写通道
var writeChan  chan <- int
writeChan = make(chan <- int)


我们需要注意的是,由于通道的阻塞特性,如果通道一直没有写入或者读取数据,会导致通道相关的goroutine陷入死锁,这个我们后面再单独讨论

结构体

golang中结构体定义如下:

type name struct {
    filedName1 type
    filedName2 type
    ....
}

可以通过如下方式进行初始化:

type Person struct{
	Name string
	Age int
}
var person Person;
person.Name = "leo"
person.Age = 31

或者:

var person = Person{Name:"leo",Age:31}
// 或者
person := Person{Name:"leo",Age:31}

或者使用new函数,但是返回的是一个指针

person := new(Person)

接口

golang中接口一般定义如下:

type interName interface{
    Method1(arg1 type1,arg2 typ2)(type3,typ4)
    Method2(arg1 type1,arg2 typ2)(type3,typ4)
}

可见性

在golang中,struct中成员、函数以及包的变量和函数如果首字母大写,则都是public,否则都是对外不可见的

值传递、指针传递

golang中默认都是值传递的,即拷贝传递,有一些值是指针,也是拷贝指针的值传递,只是通过指针可以修改原有数据

你可能感兴趣的:(golang,go,golang)