Golang
golang
安装:
http://studygolang.com/articles/1605
http://www.cnblogs.com/linuxprobe/p/5654380.html
参考:go语言编程
变量
声明
var v1 int var v2 string var v3 [10]int // 数组 var v4 []int // 数组切片 var v5 struct { f int } var v6 *int // 指针 var v7 map[string]int // map, key为string类型, value为int类型 var v8 func(a int) int
指针的使用:
package main import "fmt" func main() { var a int= 20 /* 声明实际变量 */ var ip *int /* 声明指针变量 */ ip = &a /* 指针变量的存储地址 20818a220*/ fmt.Printf("a 变量的地址是: %x\n", &a ) /* 指针变量的存储地址 20818a220*/ fmt.Printf("ip 变量储存的指针地址: %x\n", ip ) /* 使用指针访问值 20 */ fmt.Printf("*ip 变量的值: %d\n", *ip )
初始化
var v1 int = 10 // 正确的使用方式1
var v2 = 10 // 正确的使用方式2,编译器可以自动推导出v2的类型
v3 := 10 // 正确的使用方式3,编译器可以自动推导出v3的类型
(冒号和等号的组合:=),用于明确表达同时进行变量声明和初始化的工作 。
变量赋值
var v10 int
v10 = 123
多重赋值:交换
i , j = j ,i
常量 const
const Pi float64 = 3.14159265358979323846
const 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 (
Sunday = iota
Monday
Tuesday
Wednesday
Thursday
Friday
Saturday
numberOfDays // 这个常量没有导出
)
类型
布尔类型: bool。 整型: int8、 byte、 int16、 int、 uint、 uintptr等。 浮点类型: float32、 float64 复数类型: complex64、 complex128。 字符串: string。 字符类型: rune。 错误类型: error。 此外, Go语言也支持以下这些复合类型: 指针(pointer) 数组(array) 切片(slice) 字典(map) 通道(chan) 结构体(struct) 接口(interface)
字符串:
字符串不能在初始化之后修改:
str := "Hello world" // 字符串也支持声明时进行初始化的做法
str[0] = 'X' // 编译错误
字符串遍历:
str := "Hello,世界"
n := len(str)
for i := 0; i < n; i++ {
ch := str[i] // 依据下标取字符串中的字符,类型为byte
fmt.Println(i, ch)
}
str := "Hello,世界"
for i, ch := range str {
fmt.Println(i, ch)//ch的类型为rune
}
字符类型
byte类型 == int8 用于表示UTF-8字符串单个字节的值
rune表示单个unicode字符
数组
数组声明
[32]byte
[2*N] struct { x, y int32 }
[1000]*float64
[3][5]int
[2][2][2]float64
遍历:
for i := 0; i < len(array); i++ { fmt.Println("Element", i, "of array is", array[i]) } for i, v := range array { fmt.Println("Array element[", i, "]=", v) }
注意:go中数组是值类型,赋值或作为参数传递时会发生数据复制。
package main import "fmt" func modify(array [10]int) { array[0] = 10 // 试图修改数组的第一个元素 fmt.Println("In modify(), array values:", array) } func main() { array := [5]int{1,2,3,4,5} // 定义并初始化一个数组 modify(array) // 传递给一个函数,并试图在函数体内修改这个数组内容 fmt.Println("In main(), array values:", array) } 该程序的执行结果为: In modify(), array values: [10 2 3 4 5] In main(), array values: [1 2 3 4 5]
数组切片
数组的长度定义后不能改变,同时又是值类型,每次传递都会数据复制,而数据切片可以管理数据。
基于数组创建 // 先定义一个数组 var myArray [10]int = [10]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10} // 基于数组创建一个数组切片 var mySlice []int = myArray[:5] ------------------------------------ var mySlice []int = myArray[:] 基于myArray所有元素创建数组切片 var mySlice [] int = myArray[:5] 基于myArray前5个元素创建数组切片 var mySlice [] int = myArray[5:] 基于myArray第5个后面的所有元素创建数组切片 直接创建 创建一个初始元素个数为5的数组切片,元素初始值为0: mySlice1 := make([]int, 5) 创建一个初始元素个数为5的数组切片,元素初始值为0,并预留10个元素的存储空间: mySlice2 := make([]int, 5, 10) 直接创建并初始化包含5个元素的数组切片: mySlice3 := []int{1, 2, 3, 4, 5} cap()函数返回的是数组切片分配的空间大小,而len()函数返回的是数组切片中当前所存储的元素个数。数组切片支持Go语言内置的cap()函数和len()函数。
copy()内容复制
slice1 := []int{1, 2, 3, 4, 5}
slice2 := []int{5, 4, 3}
copy(slice2, slice1) // 只会复制slice1的前3个元素到slice2中
copy(slice1, slice2) // 只会复制slice2的3个元素到slice1的前3个位置
map
// PersonInfo是一个包含个人详细信息的类型 type PersonInfo struct { ID string Name string Address string } 变量声明 var myMap map[string] PersonInfo 创建 myMap = make(map[string] PersonInfo) myMap = make(map[string] PersonInfo, 100) 指定存储能力 赋值 myMap["1234"] = PersonInfo{"1", "Jack", "Room 101,..."} 删除 delete(myMap, "1234") 查找 value, ok := myMap["1234"] if ok { // 找到了 // 处理找到的value }
流程控制
if a < 5 { return 0 } else { return 1 } 关于条件语句,需要注意以下几点: 条件语句不需要使用括号将条件包含起来(); 无论语句体内有几条语句,花括号{}都是必须存在的; 左花括号{必须与if或者else处于同一行; 在if之后,条件语句之前,可以添加变量初始化语句,使用;间隔; 在有返回值的函数中,不允许将“最终的” return语句包含在if...else...结构中,否则会编译失败
switch i { case 0: fmt.Printf("0") case 1: fmt.Printf("1") case 2: fallthrough case 3: fmt.Printf("3") case 4, 5, 6: fmt.Printf("4, 5, 6") default: fmt.Printf("Default") } 在使用switch结构时,我们需要注意以下几点: 左花括号{必须与switch处于同一行; 条件表达式不限制为常量或者整数; 单个case中,可以出现多个结果选项; 与C语言等规则相反, Go语言不需要用break来明确退出一个case; 只有在case中明确添加fallthrough关键字,才会继续执行紧跟的下一个case; 可以 不设定switch之 后的条 件表达式, 在此种情况 下,整个switch结构与 多个 if...else...的逻辑作用等同。
函数
func Add(a int, b int) (ret int, err error) {
if a < 0 || b < 0 { // 假设这个函数只支持两个非负数字的加法
err= errors.New("Should be non-negative numbers!")
return
}
return a + b, nil // 支持多重返回值
}
函数调用 c := mymath.Add(1, 2)
注意:小写字母开头的函数只能本包可见,大写字母的函数才能被其他包使用。
不定参数
func myfunc(args ...int) {
for _, arg := range args {
fmt.Println(arg)
}
}
任意类型的不定参数:
func Printf(format string, args ...interface{}) {
// ...
}
多返回值
func (file *File) Read(b []byte) (n int, err Error)
n, _ := f.Read(buf)
错误处理
func Foo(param int)(n int, err error) { // ... } 调用时的代码建议按如下方式处理错误情况: n, err := Foo(0) if err != nil { // 错误处理 } else { // 使用返回值n }
func Stat(name string) (fi FileInfo, err error) {
var stat syscall.Stat_t
err = syscall.Stat(name, &stat)
if err != nil {
return nil, &PathError{"stat", name, err}
}
return fileInfoFromStat(&stat, name), nil
}
defer
//defer 执行一些清理和维护性的工作defer语句的调用是遵照 //先进后出的原则,即最后一个defer语句将最先被执行。 func CopyFile(dst, src string) (w int64, err error) { srcFile, err := os.Open(src) if err != nil { return } defer srcFile.Close() dstFile, err := os.Create(dstName) if err != nil { return } defer dstFile.Close() return io.Copy(dstFile, srcFile) }
panic()和recover()
Go语言引入了两个内置函数panic()和recover()以报告和处理运行时错误和程序中的错
误场景:
func panic(interface{})
func recover() interface{}