更多教程可参考:http://www.topgoer.com/
1.最小程序
package main
import "fmt"
func main() {
fmt.Println("Hello!")
}
2.基本数据类型
- 布尔(var b bool = false)
- 数字(int、float、complex"复数-complex64-32位实-32位虚")
- 字符串
- 派生类型(指针类型(Pointer)、数组类型、结构化类型(struct)、Channel 类型、函数类型、切片类型、接口类型(interface)、Map 类型)
3.声明
- ①指定变量类型,如:var num int64 //默认为0
- ②根据value自行判断类型,如:var str="123456" //string类型
- ③直接用":="声明并赋值,如:str := "123456" //这种方式,就不能用①中的声明方式,会报编译错误
- ④多变量声明,如:
var num1,num2,num3 int //默认都为0 var str1,str2,str3 = "012345","123456",12 var ( n1 int n2 int n3 string //默认为空字符串"" )
4.条件语句
switch与select
switch | select |
switch 语句用于基于不同条件执行不同动作,每一个 case 分支都是唯一的,从上至下逐一测试,直到匹配为止。 switch 语句执行的过程从上至下,直到找到匹配项,匹配项后面也不需要再加 break。 switch 默认情况下 case 最后自带 break 语句,匹配成功后就不会执行其他 case,如果我们需要执行后面的 case,可以使用 fallthrough | select 语句类似于 switch 语句,但是select会随机执行一个可运行的case。如果没有case可运行,它将阻塞,直到有case可运行。 每个 case 必须是一个通信操作,要么是发送要么是接收。(管道实现) |
var con = true | ch := make(chan int) |
5.循环语句
相比C,golang的for循环兼顾了for与while循环。
- 带label的break:结束执行label包含的循环
sum := 0
EXIT:
for { //while循环的作用
for i := 0; i <= 10; i++ {
sum += i
if i>=9 {
break EXIT //带label的break,会直接跳出EXIT标签包含的循环代码。不加break,只能跳出内部for循环
}
}
}
fmt.Println("sum:",sum)
- 带label的continue:继续执行label包含的循环
CONTINUEFLAG:
for i := 0; i < 5; i++ {
fmt.Println("i:", i)
for j := 0; j < 3; j++ {
fmt.Println("j:", j)
continue CONTINUEFLAG //跳到CONTINUEFLAG标签位置继续执行
}
}
- 也可以用goto:
var a int = 10
LOOP: for a < 20 {
if a == 15 {
a = a + 1
goto LOOP
}
fmt.Printf("a的值为 : %d\n", a)
a++
}
6.函数
参数传递:
- 值传递
- 引用传递(指针)
func main(){
a := 8
b := 9
swap(&a, &b)
}
func swap(x *int, y *int) { //没有返回值时,不写返回值类型。有返回值:func function_name( [parameter list] ) [return_types] {return xxx}
var temp int
temp = *x /* 保持 x 地址上的值 */
*x = *y /* 将 y 值赋给 x */
*y = temp /* 将 temp 值赋给 y */
}
闭包,内联函数:
func main() {
val := func1() //val是一个函数func
fmt.Println("val:", val()) //所以需要val()方式调用
}
func func1() func() int {
param1 := 1
return func() int {
return param1
}
}
7.数组
- 一维数组:
var array1 = [5]int{1000, 2, 3, 7, 50}
var array2 = [...]int{1000, 2, 3, 7, 50} //编译器自行推断数组长度
array3 := [5]int{1:2, 3:3} // [0 2 0 3 0]
- 二维数组:
_2darray := [][]int{}
array4 := []int{0:3,5:2}
_2darray = append(_2darray, array4)
fmt.Println(_2darray)
8.结构体
package main
import "fmt"
type Person struct { //外部函数需要调用的话,Person首字母必须大写
name string
sex string
id string
}
func main() {
//方式1
person := Person{name: "zx", sex: "男", id: "000000"}
fmt.Println(person)
//方式2
var p1 Person
p1.name="zxx"
p1.sex="男"
p1.id="1111111"
}
9.切片(动态数组)
s :=[] int {1,2,3 }
//make([]type,len,cap),len-当前长度,cap-可达最长度(可省略,省略=len)
var numbers = make([]int,3,5)
n1 := numbers[0:1] //切片截取-n = [0]
n2 := append(numbers,10,11) //追加10,11到numbers后,赋值给n2
copy(numbers,s) //将s复制给numbers,按照索引位置依次填充,如果s比numbers多,只会将s的前len(numbers)复制给numbers
10.Map(集合)
// 声明:var 变量名 map[key类型]value类型
var personMap = make(map[string]string)
personMap["A"] = "aaa"
personMap["B"] = "bbb"
fmt.Println(personMap)
delete(personMap,"A") //delete可通过key删除元素
fmt.Println(personMap)
11.Range
用于 for 循环中迭代数组(array)、切片(slice)、通道(channel)或集合(map)的元素
// 声明:var 变量名 map[key类型]value类型
var personMap = make(map[string]string)
personMap["A"] = "aaa"
personMap["B"] = "bbb"
personMap["C"] = "ccc"
for key,val := range personMap{ //遍历map,如果遍历其他类型 for index,val := range xxx{}
fmt.Println(key,val)
}
12.并发
开启一个新的 goroutine(go轻量级线程)
- 使用方式:
go func(参数列表){
线程代码逻辑
}(传入的参数)
ch := make(chan int)
c := 0
//用一个线程产生结束信号
go func(ch <-chan int) {
for {
select {
case c = <-ch:
fmt.Println(c)
case s := <-ch:
fmt.Println("s:", s)
default:
fmt.Println("sleep 5 seconds")
time.Sleep(time.Second * 5)
}
}
}(ch)
time.Sleep(time.Second * 10)
//10s后给管道ch赋值
ch <- 1
13.接口interface
借助struct实现方法
package main
import "fmt"
func main() {
var d animal
d = new(dog)
d.name()
d.action()
var c animal
c = new(cat)
c.name()
c.action()
}
type animal interface { //定义接口
name()
action()
}
type dog struct { //实现接口
}
func (d dog) action() { //实现接口方法,需要实现所有方法
fmt.Println("汪汪汪")
}
func (d dog) name() { //实现接口方法
fmt.Println("dog")
}
type cat struct {
}
func (c cat) name() {
fmt.Println("cat")
}
func (c cat) action() {
fmt.Println("喵喵喵")
}