一、GO中的变量使用
1、变量声明
GO中有三种常用的单变量声明方式
第一种:指定变量类型,声明后若不赋值,使用默认值,代码如下,声明了一个int类型的变量i,默认值为0,string默认值为空串,即"",浮点数类型默认值为0。
var i int
第二种:根据值自行判定变量的类型(类型推导),编译器会根据定义时赋值的数据类型自动判断数值类型,如下,因为赋值为10.11,所以num1被类型推到为float64类型,同理num2为int型,str为字符串型。
var num1 = 10.11
var num2 = 10
var str = "Fine!"
第三种:省略var,使用 :=,但注意,:=左侧的变量应当为未被声明的变量,否则会导致编译错误,“:”不可以省略。
同样,有单变量声明,也有多变量声明,一次性声明多个变量。
第一种:一次性声明相同类型变量,如下,声明了三个int型变量。
var n1, n2, n3 int
第二种:一次性声明多个类型不同的变量。
var n1, name, n3 = 100, "Izelern", 8.88
相当于如下声明方式:
var n1 = 100
var name = "Izelern"
var n3 = 8.88
这个声明方式同样支持类型推导以及省略var关键字的声明方式。上述声明方式还等价于:
n1, name, n3 := 100, "Izelern", 8.88
另外,在go中,函数外部定义的变量就是全局变量,如下。
package main
var n1 = 100
func main(){
}
同样的,也可以使用之前说过的单变量三种声明方式,当一次性声明多个变量时,也可以使用上述多变量一次性声明方式,只要在函数外部声明即为全局变量。
2、变量使用时注意细节
1)变量表示内存中的一个存储区域,变量的三要素为变量名、值、数据类型
2)在同一个作用域内不能重名(与C、Java的能语言同理)
二、数据类型介绍
数据类型分为基本数据类型与派生/复杂数据类型,其详细分类如下:
基本数据类型:
1.数值型,包括:
整数类型:int,int8,int16,int32,int64,uint,uint8,uint16,uint32,uint64,byte
浮点类型:float32,float64
2.字符型,但Go中没有专门的字符型,使用byte来保存单个字母字符,这是和C不相同的,采用utf-8编码方式。
3.布尔型(bool)
4.字符串(string):Go官方把string归属为基本数据类型,这与Java不同。
5.其他基本类型:
1)rune:int32的别名,表示一个Unicode码点
2)complex64,complex128
派生/复杂数据类型:
1.指针(Pointer)
2.数组
3.结构体(struct)
4.管道(Channel)
5.函数
6.切片(slice)
7.接口(interface)
8.map
1、基本数据类型介绍(数值型、字符型、布尔型、字符串)
1)数值型——整数类型
默认值为0。
与C语言大同小异,需要关注的int8中“8”代表占用存储空间为8位(bit),即1字节(byte),表示数的范围受占用存储空间影响。
int系列为有符号数,uint系列为无符号数。当不指明占用存储空间大小,即只使用“int”或“uint”时,int和uint的占用占用存储空间大小受操作系统位数影响,32位系统为4个字节(32/8 = 4byte),64位系统为8个字节(64/8 = 8byte)。
rune等价为int32,表示一个Unicode码。
byte等价为uint8,存储字符时要用byte。
注意事项:
a、Golang的整型默认声明为int型
b、格式化输出时,可以用“%T”查看某个变量的数据类型,可以用unsafe.Sizeof(目标变量)方法表示数据大小。
c、Golang程序整型变量在使用时,遵循保小不保大的原则,即:在保证程序正确运行下,尽量使用占用空间小的数据类型。
2)数值型——小数类型/浮点型
默认值为0。
主要为单精度float32和双精度float64,用于存放浮点数,表数标准同C等语言一样为IEEE754标准,存放形式为符号位+指数位+尾数位,详细原理请了解计算机组成原理中关于IEEE754标准的部分。这表明:浮点数都是有符号的,以及尾数部分可能丢失,造成精度损失。
通常情况下,要保存一个精度高的数,应当选择使用float64。Golang中默认声明的浮点数类型也为float64类型,开发中我们也推荐使用float64。
浮点常量表示方式有两种:十进制数(例如5.2323)和科学计数法(例如5.2323E2、5.2323e2等)
3)字符型
Golang中是没有专门的字符类型的,存储单个字符(字母)通常用byte类型来保存,其值为对应字母的ASCII码值,格式化输出字符时使用“%c”,若字符对应ASCII码值大于255,可以用int类型保存,其余的字符型类型的性质与C语言相似,例如:进行加减运算,utf-8编码等。
4)布尔型
默认值为false。
和其他语言的布尔型(bool)相似,取值为true和false,只占1个字节,适用于逻辑运算,一般用于程序流程控制。
5)字符串
默认值为""。
Golang的字符串是由单个字节连接起来的,使用utf-8编码标识Unicode文本
Golang中字符串是不可变的,字符串一旦赋值了,字符串就不能修改了。
Golang的字符串有两种表示形式:
a、和C等语言一样,用双引号,会识别转义字符,会将下面的'\t'、'\n'、'\\'、'\"'转义后输出
str = "Fine! \t \n \\ \""
b、用反引号,以字符串的原生形式输出,包括换行和特殊字符,可以实现防止攻击,输出源代码等效果。
str3 := `
package main
import (
"fmt"
"unsafe"
)
//演示golang中bool类型使用
func main() {
var b = false
fmt.Println("b=", b)
//注意事项
//1. bool类型占用存储空间是1个字节
fmt.Println("b 的占用空间 =", unsafe.Sizeof(b) )
//2. bool类型只能取true或者false
}
`
同样的,Go中可以使用“+”来拼接字符串,但当一行字符串过长时,转行时就需要用到“+”。
2、基本数据类型的相互转换
1)非string数据类型之间的转换
Golang和Java/C不同,Go在不同类型的变量之间赋值时不能自动转换,需要显示转换,使用如下的表达式进行。
T(v):将值v转换为类型T,如下实例中,就将n分别转换为不同数据类型赋值给对应的变量。
func main(){
var n int32 = 100
var n1 float32 = float32(n)
var n2 int8 = int8(n)
var n3 int64 = int64(n)
}
注意事项:
a、Go中的数据类型是可以从表示范围小-->表示范围大
表示范围大-->表示范围小
当从大转换为小时,编译不会报错,转换的结果是按溢出处理。
b、T(v)相当于一个输入为v,返回值为T类型的函数
2)string类型和其他基本数据类型的转换
其他基本类型转string,有两种方法:
方式1:fmt.Sprintf("%参数",表达式)
Sprintf根据format参数生成格式化的字符串并返回该字符串,参数需要和表达式的数据类型相匹配
func main(){
var num1 int = 99
var num2 float64 = 23.456
var b bool = true
var char byte = 'q'
var str string
str = fmt.Sprintf("%d",num1)
str = fmt.Sprintf("%f",num2)
str = fmt.Sprintf("%t",b)
str = fmt.Sprintf("%c",char)
}
方式2:使用strconv包的Format系列函数
Format系列函数的函数签名如下:
//bool转string
func FormatBool(b bool) string
//int转string
func FormatInt(i int64, base int) string
//其中i必须是int64类型,base表示返回的进制类型,取值在2到36之间,返回结果在会使用小写字母“a”到“z”表示大于10的数字,比如在36进制中,十进制36被表示为z
//uint转string
func FormatUint(i uint64, base int) string
//和int型类似
//float转string
func FormatFloat(f float64, fmt byte, prec, bitSize int) string
//bitSize表示参数f的来源类型,32表示float32,64表示float64
//fmt表示格式,有“f”、“b”、“e”、“E”、“g”、“G”六种参数,分别表示:
//f:-ddd.dddd
//b: -dddp±ddd,指数为二进制
//e: -d.ddde±ddd,指数为十进制
//E: -d.ddddE±dd,指数为十进制
//g: 指数很大时用“e”格式,否则“f”格式
//G: 指数很大时用“E”格式,否则“f”格式
具体看如下例子:
import strconv
func main(){
var num1 int = 99
var num2 float64 = 23.456
var b bool = true
var char byte = 'q'
var str string
str = strconv.FormatInt(int64(num1),10)
str = strconv.FormatFloat(num2,10,64)
str = fmt.Sprintf(b)
}
string转基本类型,需要使用strconv包的函数:
strconv包中字符串转换为其他基本类型,可以使用parse系列函数,它们的函数签名如下:
//转换为bool型
func ParseBool(str string)(value bool,err error)
//只接受1 、 0 、 t 、 f 、 T 、 F 、 true 、 false 、 True 、 False 、 TRUE 、 FALSE ,其它的值均返回错误
//返回值err是*NumErr类型,如果语法有误返回对应错误
//转换为int型
func ParseInt(str string, base int, bitSize int)(i int64,err error)
//base指定进制,取值为2至36;如果base为0,则会从字符串的前置判断,例如“0x”、“0”等
//bitSize指定结果必须能无溢出赋值的整数类型,0、8、16、32、64分别代表int、int8、int16、int32、int63
//返回值err是*NumErr类型,如果语法有误返回对应错误
//转换为uint型
func ParseUint(s string, base int, bitSize int) (n uint64, err error)
//与ParseInt()函数类似,但不接受正负号
//转换为float型
func ParseFloat(s string, bitSize int) (f float64, err error)
//与int系少一个进制符号而已
//返回值err是*NumErr类型,如果语法有误返回对应错误
需要注意的是,要确保string类型能够转换成有效的数据,例如,“hello”转换成一个整数的话,会直接转换为0 ,其他类型同理,会转换成默认值。
3、派生/复杂数据类型介绍
这里我们先总结指针(pointer)这一引用数据类型,其余数据类型在后面的学习中继续总结,总结完成后会在本文中添加链接。
1)指针Pointer
在Go中,指针的使用语法和C语言极为相似,在声明时在对应数据类型前面使用 “ * ” 来表明指针变量,同样,对一个变量实例,可以使用“&”来取这个变量的地址,可以用“*”对指针进行解引用。下面是声明一个int指针和取int型数据num地址的案例。
func main(){
var num int = 10
fmt.Println("&num =\n", &num)
var ptri *int = &ptri
fmt.Println("ptri = %v\n", ptri)
fmt.Println("*ptri = %v\n", *ptri)
fmt.Println("&ptri = %v\n", &ptri)
//可以看到终端分别输出了num的地址,ptri的值,ptri指向的值,ptri的地址
}
2)数组
详情见:
3)结构体(struct)
详情见:
4)管道(Channel)
待链接
5)函数
详情见:
6)切片(slice)
详情见:
7)接口(interface)
详情见:
8)map
详情见:
三、值类型和引用类型
1、值类型
基本数据类型int系列、float系列、bool、string、数组和结构体都是值类型的变量类型。
值类型的变量直接存储值,内存通常在栈中分配。
值类型都会有对应的指针类型,在相应值类型前面加*就是对应指针。
2、引用类型
指针、切片slice、map、管道chan、interface等都是引用类型。
引用类型的变量存储的是一个地址,这个地址对应的空间才是真正存储数据,内存通常在堆上分配;当没有任何一个变量引用这个地址时,该地址对应的数据空间就成为一个垃圾,由GC来回收。
四、标识符命名规范
一些命名规范与C、java类似,例如:
1、由英文字母大小写、数字0-9、以及下划线“_”组成
2、数字不能开头,可以用字母和下划线开头
3、严格区分大小写
4、不能有空格
5、不能保留关键字作为标识符
6、推荐使用驼峰法命名,即第一个词的首字母小写,后续单词的首字母大写,除非想将标识符对应变量声明为公开,见下面Golang的特性
但Golang也有自己标识符的一些特殊规则:
1、下划线“_”在Go中为空标识符,是一个特殊的标识符,可以代表任何其他的标识符,但是它对应的值会被忽略,所以仅能作为占位符使用,不能作为标识符使用。
2、如果变量名、函数名、常量名首字母大写,则可以被其他的包访问;如果首字母小写,则只能在本包中使用。可简单理解为,首字母大写为公开的,首字母小写为私有的,golang中没有访问权限修饰符。
3、保持package的名字和目录名一致,尽量采取有意义的包名,不要和标准库fmt冲突
附:系统保留关键字表和预定义标识符
break | default | func | interface | select |
case | defer | go | map | struct |
chan | else | goto | package | switch |
const | fallthrough | if | range | type |
continue | for | import | return | var |
append | bool | byte | cap | close | complex |
complex64 | complex128 | uint16 | copy | false | float32 |
float64 | imag | int | int8 | int16 | uint32 |
int32 | int64 | iota | len | make | new |
nil | panic | uint64 | println | real | |
recover | string | true | uint | uint8 | uintprt |