Files
build-web-application-with-…/2.2.md
2012-08-25 22:34:15 +08:00

264 lines
8.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#2.2 GO基础
这小节我们将要介绍如何定义变量、常量、GO内置类型以及一些GO设计中的技巧
##定义变量
GO语言里面定义变量有好几种方式。
最基本的定义变量如下go变量定义它的类型是跟在变量后面的而不是像C一样放前面
//定义一个名称为“variable_name”、类型为"type"的变量
var variable_name type
定义多个变量
//定义三个类型都是"type"的三个变量
var vname1,vname2,vname3 type
定义变量并且带有初始化的值
//初始化“variable_name”的变量为“value”值类型是"type"
var variable_name type = value
同时初始化多个变量
/*
定义三个类型都是"type"的三个变量,并且他们分别初始化相应的值
vname1为v1vname2为v2vname3为v3
*/
var vname1,vname2,vname3 type= v1, v2, v3
你是不是觉得上面这样的定义有点复杂没关系因为go语言的设计者也发现这样复杂了那么让我们来让他变的简单一点我们可以直接忽略类型这个申明那么上面的什么变成了如下
/*
定义三个变量,他们分别初始化相应的值
vname1为v1vname2为v2vname3为v3
然后他们的类型自动根据初始化的值来确定相应的类型go会帮你做这件事
*/
var vname1,vname2,vname3= v1, v2, v3
你还是觉得上面的复杂?好吧,我也觉得是,让我们继续简化
/*
定义三个变量,他们分别初始化相应的值
vname1为v1vname2为v2vname3为v3
然后他们的类型自动根据初始化的值来确定相应的类型go会帮你做这件事
*/
vname1,vname2,vname3 := v1, v2, v3
现在是不是看上去非常的简单了,`:=`这个定义直接替代了`var``type`,这样的代码是不是很简洁,但是`:=`有一个限制,那就是这个必须用在函数内部,不能在函数外部使用。
一个特殊的变量名是`_`下划线。任何赋给它的值都被丢弃。在这个例子中将赋值35赋值给b同时丢弃34。
_, b := 34, 35
Go的编译器对申明却未使用的变量会在编译阶段报错。下面的代码会产生一个错误申明了i却未使用
package main
func main() {
var i int
}
##常量
所谓常量也就是在编译阶段就确定下来的值程序运行时无法改变该值GO程序里面常量定义可以是数字类型、Bool、字符串
它的语法如下
const constant_name = value
下面是一些申明的例子
const PI = 3.1415927
const i = 10000
const Max_Thread = 10
const prefix = 'astaxie_'
当然如果需要,可以明确指定常量的类型:
const PI float32 = 3.1415927
##内置基础类型
###Boolean
对于布尔值GO的bool类型(如C++)值有:`true``false`。他的类型是:`bool`
//示例代码
var isactive bool
var enabled, disabled = true, false //忽略类型的申明
func test(){
var available bool //一般的申明
valid := false //忽略var和type的什么
available = true //赋值操作
}
###数字类型
对于整数类型有无符号和有符号两种GO同时支持`int``uint`这两种类型的长度相同但具体长度取决于编译器的实现。当前的gc和gccgo编译器在32位和64位平台上都使用32位来表示`int``uint`但未来在64位平台上可能增加到64位。GO里面也有直接定义好位数的类型`rune`, `int8`, `int16`, `int32`, `int64``byte`, `uint8`, `uint16`, `uint32`, `uint64``rune``int`的别称。`byte``uint8`的别称。
>注意一点就是这些类型之间的变量不允许相互之间赋值、操作,不然会引起编译器的错误。
>
>如下的代码会出现错误
>
> var a int8
>
> var b int32
>
> c:=a + b
浮点类型的值有`float32``float64`(没有`float`类型)。
这就是全部吗NOGo支持复数。它的变量类型是`complex128`64位实数64位虚数。如果需要小一些的还有`complex64`(32位实数32位虚数)。复数写为`re + imi``re`是实数部分,`im`是虚数部分而i 是标记`i`。使用复数的一个例子:
var c complex64 = 5+5i;
fmt.Printf("Value is: %v", c)
将会打印:(5+5i)
###字符串
前面一节里面说过字符串都是UTF-8类型的字符串通过一对`"`来定义它的类型是string
//示例代码
var french_hello string //一般申明一个变量为字符串
var empty_string string = "" // 申明了一个字符串变量,初始化为空值
func test(){
no, yes, maybe := "no", "yes", "maybe" //忽略var和type的申明同时申明多个变量
japanese_hello := "Ohaiou" //同上
french_hello = "Bonjour" //normal assignation
}
在Go中字符串是不可变的例如如下的代码编译时会报错
var s string = "hello"
s[0] = 'c'
那么如果真的想要修改怎么办呢?如下的代码可以实现
s := "hello"
c := []byte(s)
c[0] = 'c'
s2 := string(c)
fmt.Printf("%s\n", s2)
GO中可以使用`+`来链接两个字符串
s := "hello"
m := "world"
a := s + m
fmt.Printf("%s\n", a)
修改字符串也可写为
s := "hello"
s = "c" + s[1:] // 字符串虽不能更改,但可进行切片操作
fmt.Println("%s\n", s)
如果要申明一个多行的字符串怎么办?可以通过`` ` ``来申明
m:=`hello
world`
`` ` `` 括起的字符串为Raw字符串即字符串在代码中的形式就是打印时的形式没有字符转义换行也将原样输出。
###GO数据底层的存储
下面这张图来源于 Russ Cox介绍的GO数据结构大家可以看到这些基础类型底层都是开辟了一块内存然后存了相应的值
![](images/2.2.basic.png?raw=true)
###错误类型
Go内置有一个`error`类型专门用来处理错误信息GO的package里面还专门有一个包errors来处理错误
err := errors.New("emit macho dwarf: elf header corrupted")
if err != nil {
fmt.Print(err)
}
##一些技巧
###分组定义
Go语言里面针对多个同时申明变量、常量或者import多个包的时候可以采用分组的方式来申明
如下的代码
import "fmt"
import "os"
const i = 100
const pi = 3.1415
const prefix = "go_"
var i int
var pi float32
var prefix string
可以通过分组的方式写成如下
import(
"fmt"
"os"
)
const(
i = 100
pi = 3.1415
prefix = "go_"
)
var(
i int
pi float32
prefix string
)
###iota枚举
GO里面有一个关键字`iota`这个关键字用来申明enum的时候采用它默认开始值是0每调用一次加1
const(
x = iota //x == 0
y = iota //y == 1
z = iota //z == 2
w // 常量申明省略值时默认和之前一个值的字面相同。这里隐示的说w = iota,因此w==3, 其实上面y和z可以同样不用=iota
)
const v = iota // 每遇到一个const关键字iota被重置此时 v==0
##array、slice、map
###array
array就是数组它的定义如下`[n]type`,n表示数组的长度type表示存储内容的类型
对数组的操作和其他语言类似,都是通过`[]`来进行读取和赋值
var arr [10]int //申明了一个int类型的数组
arr[0] = 42 //数组下标是从0开始的
arr[1] = 13 //赋值操作
fmt.Printf("The first element is %d\n", arr[0]) //获取数据
由于数组的长度也是类型的一部分所以数组是不能改变长度的而且数组之间的赋值是值赋值当把一个数组作为一个参数传入函数的时候是这个数组的副本而不是该数组的指针如果要使用指针那么就需要用到下面介绍的slice。
数组什么可以使用另一种`:=`来申明
a := [3]int{1,2,3} //申明一个长度为3的数组
b := [10]int{1,2,3} //申明了一个长度为10的数组其中前面三个元素初始化为1、2、3其他默认为0
c := […]int{4,5,6} //可以省略长度采用…go会自动计算长度
###slice
###map
## links
* [目录](<preface.md>)
* 上一章: [你好,GO](<2.1.md>)
* 下一节: [流程和函数](<2.3.md>)
## LastModified
* $Id$