博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Go语言基础入门--变量,类型
阅读量:2392 次
发布时间:2019-05-10

本文共 6749 字,大约阅读时间需要 22 分钟。

1、变量

Go语言的变量声明方式和c/c++语言不同。Go语言引入了var关键字。变量声明如下:
var v1 int//声明一个整型变量v1var v2 stringvar v3 [10]int	//数组var v4 []int//数组切片var v5 struct { //结构体  f int}var v6 *int//指针var v7 map[string] int//map,ley为string,value为intvar v8 func(a int) int
可以看到,变量的声明没有以分号 ; 作为结束符。var关键字也可一次定义多个变量:
var (  v1 int   v2 string)
变量的初始化
var v1 int = 10 // 正确的使用方式1var v2 = 10 // 正确的使用方式2,编译器可以自动推导出 v2的类型v3 := 10 // 正确的使用方式3,编译器可以自动推导出 v3的类型
使用:= 可以减少代码的书写量,这对程序员来说是大大的好处啊
但在我们使用的过程中,不应该出现如下:
var i inti := 2//错误的做法
变量赋值
var v10 int//先声明,再赋值v10 = 123i, j = 2, 3//Go支持多重赋值
由多重赋值我们可以很方便的交换两个数的值
i, j = j, i//编译器会先计算等号右边的值,再为左边的赋值
匿名变量
Go语言支持多返回值和匿名变量
func GetName() (firstName, lastName, nickName string) { return "May", "Chan", "Chibi Maruko"}
返回了firstName, lastName, nickName,这三个变量均为string类型
我们在接收函数返回的参数时,也时可以选着性的接收,使用 _ 来忽略参数
_, _, nickName := GetName()
常量
在Go语言中,常量是指编译期间就已知且不可改变的值。常量可以是数值类型(包括整型、浮点型和复数类型)、布尔类型、字符串类型等。
//以下为字面常量-123.14159265358979323846 // 浮点类型的常量3.2+12i // 复数类型的常量true // 布尔类型的常量"foo" // 字符串常量
常量的定义
const Pi float64 = 3.14159265358979323846const zero = 0.0 // 无类型浮点常量const ( size int64 = 1024 eof = -1 // 无类型整型常量)const u, v float32 = 0, 3 // u = 0.0, v = 3.0,常量的多重赋值const a, b, c = 3, 4, "foo"// a = 3, b = 4, c = "foo", 无类型整型和字符串常量
如果常量在定义时没有限定类型,那么该常量 是一个 字面常量。常量定义的右值也可以是一个在编译期运算的常量表达式,如:
const mask = 1 << 3
由于常量的赋值是一个编译期行为,所以右值不能出现任何需要运行期才能得出结果的表达式,比如试图以如下方式定义常量就会导致编译错误:
const Home = os.GetEnv("HOME")
预定义常量
Go语言预定义了这些常量: true、 false和iota。
iota比较特殊,可以被认为是一个可被编译器修改的常量,在每一个const关键字出现时被重置为0,然后在下一个const出现之前,每出现一次iota,其所代表的数字会自动增1。
从以下的例子可以基本理解iota的用法:
const (  // iota被重设为 0c0 = iota // c0 == 0c1 = iota // c1 == 1c2 = iota // c2 == 2)const (a = 1 << iota // a == 1 (iota在每个const开头被重设为 0)b = 1 << iota // b == 2c = 1 << iota // c == 4)const (u = iota * 42 // u == 0v float64 = iota * 42 // v == 42.0w = iota * 42 // w == 84)const x = iota // x == 0 ( 因为 iota又被重设为 0了 )const y = iota // y == 0 ( 同上)
如果两个const的赋值语句的表达式是一样的,那么可以省略后一个赋值表达式。因此,上面的前两个const语句可简写为:
const ( // iota被重设为 0c0 = iota // c0 == 0c1 // c1 == 1c2 // c2 == 2)const (a = 1 <

枚举

枚举指一系列相关的常量,比如下面关于一个星期中每天的定义。通过上一节的例子,我们看到可以用在const后跟一对圆括号的方式定义一组常量,这种定义法在Go语言中通常用于定义枚举值。 Go语言并不支持众多其他语言明确支持的enum关键字。
const (Sunday = iotaMondayTuesdayWednesdayThursdayFridaySaturdaynumberOfDays // 这个常量没有导出)
同Go语言的其他符号( symbol)一样,以
大写字母开头的常量在包外可见。以上例子中numberOfDays为包内私有,其他符号则可被其他包访问。

类型

Go语言内置以下这些基础类型:
 布尔类型: bool。
 整型: int8、 byte、 int16、 int、 uint、 uintptr等。
 浮点类型: float32 、 float64。
 复数类型: complex64、 complex128。
 字符串: string。
 字符类型: rune。
 错误类型: error。
此外, Go语言也支持以下这些复合类型:
 指针( pointer)
 数组( array)
 切片( slice)
 字典( map)
 通道( chan)
 结构体( struct)
 接口( interface)
在这些基础类型之上Go还封装了下面这几种类型: int、 uint和uintptr等。这些类型的特点在于使用方便,但使用者不能对这些类型的长度做任何假设。对于常规的开发来说,用int和uint就可以了,没必要用int8之类明确指定长度的类型,以免导致移植困难。
bool类型
Go语言中的布尔类型与其他语言基本一致,关键字也为bool,可赋值为预定义的true和false示例代码如下:
var v1 boolv1 = truev2 := (1 == 2) // v2也会被推导为 bool类型
布尔类型不能接受其他类型的赋值,不支持自动或强制的类型转换。以下的示例是一些错误的用法,会导致编译错误:
var b boolb = 1 // 编译错误b = bool(1) // 编译错误以下的用法才是正确的:var b boolb = (1!=0) // 编译正确fmt.Println("Result:", b) // 打印结果为 Result: true
整型
1. 类型表示
需要注意的是, int和int32 在Go语言里被认为是两种不同的类型,编译器也不会帮你自动做类型转换,比如以下的例子会有编译错误:
var value2 int32value1 := 64 // value1将会被自动推导为 int类型value2 = value1 // 编译错误
使用强制类型转换可以解决这个编译错误:
value2 = int32(value1) // 编译通过
当然,开发者在做强制类型转换时,需要注意数据长度被截短而发生的数据精度损失(比如将浮点数强制转为整数)和值溢出(值超过转换的目标类型的值范围时)问题。
2. 数值运算
Go语言支持下面的常规整数运算: +、 -、 *、 /和%。加减乘除就不详细解释了,需要说下的是, % 和在C语言中一样是求余运算,比如:
5 % 3 // 结果为: 2
3. 比较运算
Go语言支持以下的几种比较运算符: >、 <、 ==、 >=、 <=和!=。这一点与大多数其他语言相同,与C语言完全一致。
下面为条件判断语句的例子:
i, j := 1, 2if i == j { fmt.Println("i and j are equal.")}
两个不同类型的整型数不能直接比较,比如int8类型的数和int类型的数不能直接比较,但各种类型的整型变量都可以直接与字面常量( literal)进行比较,比如:
var i int32var j int64i, j = 1, 2if i == j {  // 编译错误 fmt.Println("i and j are equal.")}if i == 1 || j == 2 { // 编译通过 fmt.Println("i and j are equal.")}
4. 位运算
Go语言的大多数位运算符与C语言都比较类似,除了取反在C语言中是~x,而在Go语言中是^x。
浮点型
浮点型用于表示包含小数点的数据,比如1.234就是一个浮点型数据。 Go语言中的浮点类型采用IEEE-754标准的表达方式。
1. 浮点数表示
Go语言定义了两个类型float32 和float64 ,其中float32 等价于C语言的float 类型,
float64等价于C语言的double类型。
在Go语言里,定义一个浮点数变量的代码如下:
var fvalue1 float32fvalue1 = 12fvalue2 := 12.0 // 如果不加小数点, fvalue2会被推导为整型而不是浮点型
对于以上例子中类型被自动推导的fvalue2 ,需要注意的是其类型将被自动设为float64,而不管赋给它的数字是否是用32位长度表示的。因此,对于以上的例子,下面的赋值将导致编译
错误:
fvalue1 = fvalue2
而必须使用这样的强制类型转换:
fvalue1 = float32(fvalue2)
2. 浮点数比较
因为浮点数不是一种精确的表达方式,所以像整型那样直接用==来判断两个浮点数是否相等是不可行的,这可能会导致不稳定的结果。
下面是一种推荐的替代方案:
import "math"// p为用户自定义的比较精度,比如0.00001func IsEqual(f1, f2, p float64) bool { return math.Fdim(f1, f2) < p}
复数类型
复数实际上由两个实数(在计算机中用浮点数表示)构成,一个表示实部( real),一个表示虚部( imag)。如果了解了数学上的复数是怎么回事,那么Go语言的复数就非常容易理解了。
1. 复数表示
复数表示的示例如下:
var value1 complex64 // 由2个float32构成的复数类型value1 = 3.2 + 12ivalue2 := 3.2 + 12i // value2 是complex128类型value3 := complex(3.2, 12)  // value3 结果同  value2
2. 实部与虚部
对于一个复数z = complex(x, y) ,就可以通过Go语言内置函数real(z) 获得该复数的实
部,也就是x,通过imag(z) 获得该复数的虚部,也就是y。
更多关于复数的函数,请查阅math/cmplx标准库的文档。
字符串
在Go语言中,字符串也是一种基本类型。相比之下, C/C++语言中并不存在原生的字符串类型,通常使用字符数组来表示,并以字符指针来传递。
Go语言中字符串的声明和初始化非常简单,举例如下:
var str string // 声明一个字符串变量str = "Hello world" //字符串赋值ch := str[0] // 取字符串的第一个字符fmt.Printf("The length of \"%s\" is %d \n", str, len(str))fmt.Printf("The first character of \"%s\" is %c.\n", str, ch)
输出结果为:
The length of "Hello world" is 11The first character of "Hello world" is H.
字符串的内容可以用类似于数组下标的方式获取,但与数组不同,字符串的内容不能在初始化后被修改,比如以下的例子:
str := "Hello world" // 字符串也支持声明时进行初始化的做法str[0] = 'X' // 编译错误
在这个例子中我们使用了一个Go语言内置的函数len() 来取字符串的长度。这个函数非常有用,我们在实际开发过程中处理字符串、数组和切片时将会经常用到。
本节中我们还顺便示范了Printf() 函数的用法。有C语言基础的读者会发现, Printf() 函数的用法与C语言运行库中的printf() 函数如出一辙。读者在以后学习更多的Go语言特性时,可以配合使用Println() 和Printf() 来打印各种自己感兴趣的信息,从而让学习过程更加直观、有趣。
Go编译器支持UTF-8的源代码文件格式。这意味着源代码中的字符串可以包含非ANSI的字符,比如“Hello world. 你好,世界!”可以出现在Go代码中。但需要注意的是,如果你的Go代
码需要包含非ANSI字符,保存源文件时请注意编码格式必须选择UTF-8。特别是在Windows下一般编辑器都默认存为本地编码,比如中国地区可能是GBK编码而不是UTF-8,如果没注意这点在编译和运行时就会出现一些意料之外的情况。
字符串的编码转换是处理文本文档(比如TXT、 XML、 HTML等)非常常见的需求,不过可惜的是Go语言仅支持UTF-8和Unicode编码。对于其他编码, Go语言标准库并没有内置的编码转换支持。不过,所幸的是我们可以很容易基于iconv库用Cgo包装一个。这里有一个开源项目:
https://github.com/xushiwei/go-iconv。
1. 字符串操作
更多的字符串操作,请参考标准库strings包。
2. 字符串遍历
Go语言支持两种方式遍历字符串。一种是以字节数组的方式遍历:
str := "Hello, 世界"n := len(str)for i := 0; i < n; i++ { ch := str[i] // 依据下标取字符串中的字符,类型为 byte fmt.Println(i, ch)}
这个例子的输出结果为:
0 721 1012 1083 1084 1115 446 327 2288 1849 15010 23111 14912 140
可以看出,这个字符串长度为13。尽管从直观上来说,这个字符串应该只有9个字符。这是因为每个中文字符在UTF-8中占3个字节,而不是1个字节。
另一种是以Unicode字符遍历:
str := "Hello, 世界"for i, ch := range str { fmt.Println(i, ch)//ch的类型为 rune}
输出结果为:
0 721 1012 1083 1084 1115 446 327 1999010 30028
以Unicode字符方式遍历时,每个字符的类型是rune(早期的Go语言用int类型表示Unicode
字符),而不是byte。
字符类型
在Go语言中支持两个字符类型,一个是byte(实际上是uint8的别名),代表UTF-8字符串的单个字节的值;另一个是rune,代单个Unicode字符。
关于rune相关的操作,可查阅 Go标准库的unicode包。另外unicode/utf8 包也提供了UTF8和Unicode之间的转换。出于简化语言的考虑, Go语言的多数API都假设字符串为UTF-8编码。尽管Unicode字符在标准库中有支持,但实际上较少使用。
你可能感兴趣的文章
四个开源商业智能平台比较 (一)
查看>>
WinEdt如何使用中文
查看>>
Programmatic PlyQL via HTTP, ODBC, and JDBC
查看>>
Jackson 处理复杂类型(List,map)两种方法
查看>>
使用Apache Common的FileUpload的一点点注意事项
查看>>
arduino连接热敏打印机的资料
查看>>
用zxing生成条形码
查看>>
如何将OpenShift与eclipse集合使用
查看>>
Build Your Own PaaS on RHEL 6
查看>>
关于JAX-RS的导引阅读
查看>>
Markdown编辑器editor.md的使用
查看>>
FileServlet supporting resume and caching and GZIP
查看>>
spring boot etag header example
查看>>
关于大数据的两个大分支
查看>>
spring boot Websocket
查看>>
关于企业到个人的转账
查看>>
Angular4中调用js代码
查看>>
JAVA8-用lamda表达式和增强版Comparator进行排序
查看>>
Oracle 12CR2 Oracle Restart - ASM Startup fails with PRCR-1079
查看>>
poj 2140 Herd Sums
查看>>