Go的基本设计理念是:编译效率,运行效率和开发效率要三者兼顾。
【特性】
1、并行机制\协程-多核应用、网络应用
2、结构化类型-弹性模块化程序
3、机器码编译、GC、反射
4、静态类型语言-运行效率
编译器: GCCgo\6g\8g
【环境变量】
a.添加系统变量GOROOT = C:\Go
b.修改环境变量PATH = %GOROOT%\bin
c.添加系统变量GOPATH:用来设置包加载路径的重要变量,可设置多个路径,设置项目路径可下载各种依赖关系。
【关键词】
var const func type struct map interface
select defer chan fallthrough range
【数据类型】
布尔类型
数字类型
字符串类型
派生类型:
(a) 指针类型(Pointer)
(b) 数组类型
(c) 结构化类型 (struct)
(d) 联合体类型 (union)
(e) 函数类型
(f) 切片类型
(g) 接口类型(interface)
(h) Map 类型
(i) Channel 类型
& 返回地址变量
* 返回指针变量
有符号整数
int (位数随系统,默认)
int8 (-128~127)
int16 (-32768~32767)
int32 (-2147483648~2147483647)(类似rune)
int64
无符号整数
uint (位数随系统)
uint8 (0~255)(类似byte)
uint16 (0~65535)
uint32 (0~4294967295)
uint64
uintptr 用于存放指针
浮点 float32 float64 (默认)
复数 complex64 complex128
【变量定义】并行赋值
var vname1, vname2 type //声明后若不赋值使用默认值
var vname1, vname2 = val1, val2 //根据值自行判定变量类型
vname1, vname2 := val1, val2 //:=格式只能用在函数体内,注意 :=左侧变量不能是已经声明过的,否则编译错误
var (
vname1 v_type1
vname2 v_type2
)
交换两个变量的值,可以简单地使用 a, b = b, a
val1, val2 = ReturnVals() //一个函数多个返回值
var a int=1
var b, c, d = -1, 2.0, true
e:="foo"
const MAX int = 100
var ptr *int=&a //指针初始化为nil,值为0,ptr==nil
var ptr2 **int=&ptr//指针的指针
fmt.Println("Hello World!")
fmt.Println("a=",a,", b=",b)
fmt.Println("a=%d, b=%d",a,b)
fmt.Println(a,b,c,d,e,ptr,ptr2) //int int float64 bool string *int **int
fmt.Printf("val: %d %f %s %d %d %x \n", a,c,e,*ptr,ptr) //格式输出
常量可用作枚举
const (
Female = 1
Male = 2
)
常量可用len(), cap(), unsafe.Sizeof() 计算表达式,函数必须是内置函数
import "unsafe"
const (
a = "abc"
b = len(a)
c = unsafe.Sizeof(a)
)
iota 特殊常量,每出现一次iota自动加1,在每次const关键字出现时被重置为0
const (
a = iota //0
b //1
c = "ha" //独立值,iota += 1
d //"ha" iota += 1
e = iota //4,恢复计数
f //5
)
const (
i=1<<iota //i=1<<0
j=3<<iota //j=3<<1
k //k=3<<2
l //l=3<<3
)
【switch有两种类型】
switch var1 可以是任何类型
switch 语句不需加break
表达式Switch
var grade string = "B"
var marks int = 90
switch marks { //对值分支
case 90: grade = "A"
case 80: grade = "B"
case 60,70 : grade = "C"
default: grade = "D"
}
switch { //对表达式分支
case grade == "A" :
fmt.Printf("Excellent!\n" )
case grade == "B", grade == "C" :
fmt.Printf("Well done\n" )
case grade == "D" :
fmt.Printf("You passed\n" )
case grade == "F":
fmt.Printf("Better try again\n" )
default:
fmt.Printf("Invalid grade\n" );
}
类型Switch
switch x.(type){
case type:
statement(s);
default:
statement(s);
}
var x interface{} //必须有接口的变量表达式{}输入
switch i := x.(type) {
case nil:
fmt.Printf("%T",i)
case int:
fmt.Printf("x is int")
case float64:
fmt.Printf("x is float64")
case func(int) float64:
fmt.Printf("x is func(int)")
case bool, string:
fmt.Printf("x is bool or string")
default:
fmt.Printf("don't know the type")
}
select是一个控制结构,类似于用于通信的switch语句。每个case必须是一个通信操作,要么是发送要么是接收。
如果有多个case都可以运行,Select会随机执行一个,其他不会执行。
如果没有case可运行(没有default),它将阻塞,直到有case可运行。
func main() {
var c1, c2, c3 chan int
var i1, i2 int
select {
case i1 = <-c1:
fmt.Printf("received ", i1, " from c1n")
case c2 <- i2:
fmt.Printf("sent ", i2, " to c2n")
case i3, ok := (<-c3): // same as: i3, ok := <-c3
if ok {
fmt.Printf("received ", i3, " from c3n")
} else {
fmt.Printf("c3 is closedn")
}
default:
fmt.Printf("no communicationn")
}
}
【for循环有三种】
for [condition | ( init; condition; increment ) | Range] { }
for a := 0; a < 10; a++ { }
for a < b { } //while
for { } //for(;;) for true {}
for 循环的 range 可以对 数组、切片、字符串、集合等进行迭代循环
for index, value := range numbers1 { } //数组
for _, value := range slice1 { } //切片不需索引使用_占位
for key, value := range map1 { }
for i, c := range "go" { } //枚举Unicode字符串
//goto跳转-避免使用
var a int = 10
LOOP: for a < 20 {
if a == 15 {
a = a + 1
goto LOOP
}
fmt.Printf("%d\n", a)
a++
}
【数组】-定长
var numbers1 [5] int //[0 0 0 0 0]
var numbers2 = [5]int{1, 2, 3, 4} //[1 2 3 4 0]
var numbers3 = []int{1, 2, 3, 4} //[1 2 3 4]
var numbers4 [5][5] int
fmt.Println(numbers1)
var ptr [5] *int //指针数组,不是指向数组的指针
for i := 0; i < 5; i++ {
ptr[i] = &numbers2[i]
fmt.Println(*ptr[i])
}
for i:= range numbers2 {
fmt.Println(i,"=",numbers2[i])
}
//数组参数必须定义一致才能传递
void myFunction(param [5]int) //param := [5]int{1, 2, 3, 4}
void myFunction(param []int) //param := []int{1, 2, 3, 4}
【切片】-抽象数组-不定长
var numbers1 [] int //未初始化前默认为 nil,长度容量为零
printSlice(numbers1) //len=0 cap=0 slice=[]
numbers1 = []int{0,1,2,3,4,5,6,7,8}
printSlice(numbers1) //len=9 cap=9 slice=[0 1 2 3 4 5 6 7 8]
printSlice(numbers1[:]) //同上
printSlice(numbers1[1:5]) //len=4 cap=8 slice=[1 2 3 4]
printSlice(numbers1[5:]) //len=4 cap=4 slice=[5 6 7 8]
printSlice(numbers1[:5]) //len=5 cap=9 slice=[0 1 2 3 4]
numbers1 = make([]int,3,5) //创建切片
printSlice(numbers1) //len=3 cap=5 slice=[0 0 0]
//想增加切片的容量,必须创建一个新的更大的切片并把原分片的内容都拷贝过来
numbers2 := make([]int, len(numbers1), (cap(numbers1))*2)
copy(numbers2,numbers1) //numbers1复制到numbers2
printSlice(numbers2) //len=3 cap=10 slice=[0 0 0]
numbers1 = append(numbers1, 9,10)
printSlice(numbers1) //len=11 cap=18 slice=[0 1 2 3 4 5 6 7 8 9 10]
func printSlice(x []int){
fmt.Printf("len=%d cap=%d slice=%v\n",len(x),cap(x),x)
}
【管道】
【集合】
var map1 map[string]string = make(map[string]string) //make定义
map1 = map[string] string {"a":"A","b":"B"} //定义
map1["c"]="C"
delete(map1,"b");
for k,v := range map1 {
fmt.Println(k,"=",v)
}
v, ok := map1["a"]
if(ok){
fmt.Println("a present", v)
}
【结构体】
type Books struct {
title string
author string
book_id int
}
var book1 Books
book1.title = "Go语言"
book2 := Books{"Go语言第2版", "xx","B01"}
book1=book2 //副本
var book3 *Books //结构体指针
book3=&book2 //引用
book3.title = "Go语言第3版" //访问成员跟变量一样
【函数】
func function_name( [parameter list] ) [return_types] {
/* 函数实现 */
}
func getSum(num1, num2 int) int {
return num1+num2
}
getSum := func(num1, num2 int) int { //定义函数变量,函数作值
return num1+num2
}
func swap(x, y int)(int, int){ //函数返回多个值
return y,x
}
func swap1(x, y int){
temp := x
x = y
y = temp
}
func swap2(x, y *int){ //指针参数
temp := *x
*x = *y
*y = temp
}
func main() {
a, b :=1,2
fmt.Println(getSum(1, 2))
swap(a,b)
fmt.Println(a, b) //1,2
swap2(&a,&b)
fmt.Println(a, b) //2,1
}
【函数作闭包-匿名函数】
匿名函数的优越性在于可以直接使用函数内的变量,不必申明
//函数getSequence() 返回另外一个函数,该函数的目的是在闭包中递增 i 变量
func getSequence() func() int {
i:=0
return func() int {
i++
return i
}
}
func main(){
nextNumber := getSequence()
fmt.Println(nextNumber(),nextNumber())//1,2
nextNumber1 := getSequence() //重新返回函数i从0开始
fmt.Println(nextNumber1(),nextNumber1())//1,2
}
【函数方法】
func (v_name v_type) function_name() [return_type] {}
【接口】
/* 定义接口 */
type interface_name interface {
method_name1 [return_type]
method_name2 [return_type]
}
/* 定义结构体 */
type struct_name struct {
/* variables */
}
/* 实现接口方法 */
func (struct_name_variable struct_name) method_name1() [return_type] {
/* 方法实现 */
}
// 定义结构体(子类),实现接口方法
type Phone interface { //定义接口
call()
}
type NokiaPhone struct { //定义结构体(子类)
}
func (nokiaPhone NokiaPhone) call() { //实现接口方法
fmt.Println("I am Nokia, I can call you!")
}
type IPhone struct { //定义结构体(子类)
}
func (iPhone IPhone) call() { //实现接口方法
fmt.Println("I am iPhone, I can call you!")
}
func main() {
var phone Phone
phone = new(NokiaPhone)
phone.call()
phone = new(IPhone)
phone.call()
}
type Shape interface {
area() float64
}
type Rectangle struct {
x,y float64
}
//属于Rectangle对象的方法、实现接口Shape.area()
func(rectangle Rectangle) area() float64 {
return rectangle.x * rectangle.y
}
//给Shape定义方法
func getArea(shape Shape) float64 {
return shape.area()
}
func printRectangle(rectangle1 Rectangle,rectangle2 *Rectangle){
fmt.Println(rectangle1,rectangle2)
rectangle1.x=2
rectangle2.x=2//改变了参数值
}
func main(){
//传参数值变化
var rectangle1,rectangle2 Rectangle
rectangle1.x=1
rectangle2.x=1
printRectangle(rectangle1,&rectangle2)
fmt.Println(rectangle1,rectangle2)
//接口方法调用
rectangle3 := Rectangle{x:1,y:2} //指定参数赋值不受顺序、数量限制
fmt.Println(rectangle3,rectangle3.area(),getArea(rectangle3))
}
有疑问加站长微信联系(非本文作者)