优势:
- 极简单的部署方式:可直接编译成机器码,不依赖其他库,直接运行即可部署
- 静态类型语言:
- 编译的时候检查出来隐藏的大多数问题
- 语言层面的并发:
- 天生支持
- 充分利用多核
- 标准库:
- runtime系统调度机制
- 高效的GC垃圾回收
- 丰富的标准库
- 简单易学
- 25个关键字
- C语言简洁基因
- 跨平台
- 面向对象
缺点:
- 无泛化类型
- 包管理大部分都在github上
- 所有Exception都用error来处理
- 对C的降级处理不是无缝的,不像C->asm那么完美(序列化问题)
Hello world
package mainimport ("fmt")func main(){var a int = 1fmt.Println("hello go!")}
变量,常量
变量 var
有var就是=
没有就是:=
方法1:声明一个变量,默认值是0var a int//默认a=0方法2:声明一个变量并初始化var b int = 10方法3:初始化时省略数据类型,自动匹配var c = 10//自动推导方法4:直接自动匹配//不支持全局变量d:= 10
多个变量声明
单行写法var aa,bb int =100,200var cc,dd = 100, "miao"多行写法var(vv int = 100gg bool = true)
常量,枚举,const与iota
const 关键字可以用于定义常量const a int = 10const还可以定义枚举类型,iota用在const中作为一个每行+1的量 第一行iota=0 公式不变const (SHANGHAI = 1SHENZHEN = 2BEIJING = 3)与以下是一样的const (SHANGHAI = iotaSHENZHENBEIJING)//=================================const (SHANGHAI = 10*iotaSHENZHENBEIJING)相当于const (SHANGHAI = 0SHENZHEN = 10BEIJING = 20)//================================const (a,b = iota + 1, iota +2 //1,2c,d //2,3e,f = iota*2, iota*3 //6,9c,d //8,12)
函数,多返回值
多返回值
func foo1(a string, b int) {blabla}func foo2(a string, b int) int {blablac:=10return c}func foo3(a string, b int) (int,int) {blablac,d:=10,20return c,d}func foo4(a string ,b int)(r1 int,r2 int){r1:=10r2:=20 //不赋值则默认0//作用域是函数体整个空间内return}
通常把对外开放的函数大写开头,私有函数小写开头
init函数与import导包

先层层import,init()执行后再返回
引入路径填相对于gopath的路径
可以给包起别名
import(_ "xxxx/xxxx" //匿名导入 可以不使用包内方法,但是initmylib "yyyy" //mylib.AAA() 可以使用包的方法"qqqqq/cccc". "qqqqqqqqqq" //导入包中的全部方法 可以直接调用不需要加包名)
指针,引用
p 根据地址找内存
&a 取地址
p := &a p是int类型的
可以多多多级指针
defer
defer后面的表达式在结束之前执行,类似于析构函数,是一种压栈的形式
return先执行,defer后执行
func A(){}func B(){}func C(){}func E(){}func main(){defer A()defer B()defer C()defer fmt.Println("D")return E()}EDCBA
数组,切片slice
var myArray1 [10]int //普通数组var myArray2 [4]int{1,2,3,4} //普通数组for i:=0 ;i< len(myArray1);i++ {fmt.Println(myArray1[i])}for index,value := range myArray2{fmt.Println("index=",index,"value=",value)}数组在函数中传递时候传递的是一个拷贝的值,且根据不同的长度有不同的类型myArray1 的类型是[10]int, myArray2的类型是[4]int,在函数传递的时候会类型不匹配func A(arr [4]int) {arr[0]=10 //无法改变实际上的arr[0]}
切片数组
myArray:=[]int{1,2,3,4}func A(arr []int) {//引用传递arr[0]=10 //可以改变实际上的arr[0],传的是一个指针}
slice四种声明方式
var a =make([]int,15)slice1 := []int{1,2,3}var slice2 []intslice2 = make([]int,3)var slice3 []int =make([]int,3)slice4 := make([]int,3)
判断slice是否为空
if slice1 == nil {blabla 空切片}else{blabla 分配过的切片}
slice切片与追加
var a =make([]int,3,5) //长度3容量5a=append(a,1) //长度4容量5a=append(a,2) //长度5容量5a=append(a,3) //长度6容量10 超出容量的时候容量会x2var b =make([]int,3) //长度3容量3 如果扩容就变成6
扩容机制:超出容量的时候容量会x2
截取
s := []int{1,2,3}s1 := s[0:1] //前闭后开,和python一样 默认上限len(s),默认下限0 [1:], [:2]都是可以的
这里指向的底层地址一致,改s1[0]也会改变s[0]
可以用copy得到深拷贝
s2:= mask([]int,3)copy(s2,s) //s中的值拷贝至s2
map
三种声明方式//方法1声明 MyMap1是一种map类型,key是string,value是intvar myMap1 map[string]int目前myMap1==nilmyMap1=make(map[string]int,10) 使用map前需要先用make给map分配数据空间 一样能够自动扩容myMap1["one"]=10myMap2["two"]=20必须make否则会报错//方法2myMap2 := make(map[string]int)myMap2["one"]=10myMap2["two"]=20//方法3myMap3 := map[string]string{"one":10,"two":20,}//===========================使用//===========================//添加 略//遍历for key,value := range myMap3{fmt.Println(key,value)}//删除delete(myMap3,"one")//修改和添加一样//传参的时候传的是指针func changeMap(mapa map[string]int){ //引用传递mapa["one"]=1}//完全拷贝需要再定义一个map把值复制过去
struct类与对象
type myint int//声明一个int的别名叫myint//定义一个结构体type Book struct{title stringauth string}func changeBook1(book Book){ //值传递book.auth = "444" //不会变}func changeBook2(book *Book){book.auth = "111" //会变}func main(){var book1 Bookbook1.title = "golang"book1.auth = "zhang3"fmt.Printf("%v\n",book1)//会逐个输出Book中的变量值//输出的会是 {golang zhang3}changeBook1(book)fmt.Printf("%v\n",book1)//输出的会是 {golang zhang3}changeBook2(&book1)fmt.Printf("%v\n",book1)//输出的会是 {golang 111}}
类
//如果类名首字母大写表示其他包也能够定义这个对象type Hero struct{Name string //如果说类的属性首字母大写表示该属性共有,否则的话只能够类的内部访问Ad intlevel int //私有属性}func (this *Hero) Show(){ //方法首字母大写表示在其他包中能够调用 小写表示其他包不能调用fmt.Println("",........)}func (this Hero) SetName(a strnig){ //这里传递的是this的一个拷贝this.Name=a}func (this *Hero) SetName(a string){this.Name=a}
- 注意this* 否则只能访问一个副本
- 注意首字母大小写有区别,大写表示对外访问,小写只能在本包内访问
继承
type Human struct{name stringsex string}func (this *Human) Eat(){fmt.Println("Human.Eat()")}func (this *Human) Walk(){fmt.Println("Human.Walk()")}typedef Superman struct{Human //Superman类继承了Human类的方法level int}//重定义父类方法func (this* Superman) Eat(){fmt.Println("Superman.Eat()")}//子类新方法func (this* Superman) Fly(){fmt.Println("Superman.Eat()")}func main(){h:=Human{"zhang3","female"}h.Eat()h.Walk()s:=Superman{Human{"li4","male"},88}//或者var s Supermans.name = "li4"s.sex = "male"s.level = 88s.Walk() //human walks.Eat() //superman eats.Fly() //superman fly}
多态 interface
基本要素
- 有一个父类
- 有子类,实现了父类的全部接口方法
- 父类类型的变量(指针) 指向(引用) 子类的具体数据变量
```go
type AnimalIF interface{ //是一个指针!!!!!!!!!!!!!!!!
Sleep()
GetColor() string //获取动物的颜色 GetType() string //获取动物的种类 }
//不需要把AnimalIF显式写下来,重写该接口的[所有]方法,就可以用一个AnimalIF指针指向Cat type Cat struct{ color string }
func (this* Cat) GetColor(){ return this.color }
func (this* Cat) GetType(){ return “Cat” }
func (this* Cat) Sleep(){ fmt.Println(“Cat sleeping”) }
type Dog struct{ color string }
func (this* Dog) GetColor(){ return this.color }
func (this* Dog) GetType(){ return “Dog” }
func (this* Dog) Sleep(){ fmt.Println(“Dog sleeping”) }
func showAnimal (animal AnimalIF){ animal.Sleep() //多态 fmt.Println(“color = “,animal.GetColor()) }
func main(){
var animal AnimalIF //接口数据类型animal = &Cat{"Green"}animal.Sleep()animal = &Dog("Yellow")animal.Sleep()showAnimal(animal)
<a name="gs0sb"></a>## 空接口 interface{} 通用万能类型,类型断言int、string、float32、float64、struct 都实现了 interface```gofunc myFunc(arf interface{}){fmt.Println("myFunc called")fmt.Println(arg)//interface{}实际类型区分办法:断言value,ok := arg.(string)if ok{是string类型}else{不是string类型fmt.Printf("value type is %T\n", value)}}type Book struct{auth string}func main(){bool:= Book{"Golang"}myFunc(book)myFunc(100)}
反射
变量的结构

反射 通过一个变量得到type、值
var a string//pair<statictype:string, value:"aceld">a="aceld"//pair<type:string,value:"aceld">var allType interface{}allType = astr,_:=allType.(string)fmt.Println(str) //aceld
断言可以用于强制转换

pair是不会变的.
reflect包:ValueOf,TypeOf
动态获取未知数据类型和值
package mainimport("fmt""reflect")func reflectNum(arg interface{}){fmt.Println("type:", reflect.TypeOf(arg)," value:",reflect.ValueOf(arg))}type User struct{Id intName stringAge int}func (this* User) Call(){fmt.Println("User id called ..")fmt.Printf("%v\n", this)}func man(){var num float64 = 1.2345user:= User{1,"Aceld",18}}func DoFIleAndMethod(input interface{}){//获取typeinputType:= reflect.TypeOf(input)fmt.Prinln("type is ",inputType.Name())//获取valueinputValue:= reflect.ValueOf(input)fmt.Prinln("value is ",inputValue)//通过type获取里面的字段for i :=0; i< inputType.NumField(); i++{field := inputType.Field(i)value := inputValue.Field(i).Interface()fmt.Printf("%s:%v = %v\n",field.Name,field.Type,value)}//通过type获取里面的方法,调用for i := 0; i< inputType.NumMethod();i++{m:=inputType.Method(i)fmt.Printf("%s:%v\n",m.Name,m.Type)}}

详细接口看文档
结构体标签
type resume struct{Name string `info:"name" doc:"我的名字"`Sex string `info:"sex"`}func findTag(str interface{}){t:=reflect.TYpeOf(str).Elem()for i:=0; i<t.NumField();i++{taginfo :=t.Field(i).Tag.Get("info")tagdoc := t.Field(i).Tag.Get("doc")}}func main(){var re resumefindTag(&re)}
结构体标签在json中的使用

可以应用在json编解码,orm映射关系等

