go语言介绍

基本概念

  • Go是静态类型的语言,它的类型系统没有层级。
  • Go完全是垃圾回收型的语言,并为并发执行与通信提供了基本的支持。
  • 按照其设计,Go打算为多核机器上系统软件的构造提供一种方法。

gopath

  • Unix:export GOPATH=/home/apple/mygo
  • win32:GOPATH=c:\mygo,新建一个环境变量GOPATH并赋值,像处理path变量一样
  • 当有多个GOPATH时,默认会将go get的内容放在第一个目录下
  • $GOPATH 目录约定有三个子目录
    • src 存放源代码(比如:.go .c .h .s等)
    • pkg 编译后生成的文件(比如:.a)
    • bin 编译后生成的可执行文件(为了方便,可以把此目录加入到 \(PATH 变量中,如果有多个gopath,那么使用\){GOPATH//😕/bin:}/bin添加所有的bin目录)

常见命令

  • go install,进入对应的应用包目录编译应用
  • go build,编译程序
    • 如果是普通包,执行go build之后,它不会产生任何文件。如果是main包,当你执行go build之后,它就会在当前目录下生成一个可执行文件。
    • 可以指定编译输出的文件名:go build -o oo.exe
    • go build命令默认会编译当前目录下的所有go文件但会忽略目录下以“_”或“.”开头的go文件
    • 如果你的源代码针对不同的操作系统需要不同的处理,那么你可以根据不同的操作系统后缀来命名文件。
  • go get,获取远程包(go get本质上可以理解为首先第一步是通过源码工具clone代码到src下面,然后执行go install)。go get -u 参数可以自动更新包,而且当go get的时候会自动获取该包依赖的其他第三方包。通过这个命令可以获取相应的源码,对应的开源平台采用不同的源码控制工具,例如github采用git、googlecode采用hg,所以要想获取这些源码,必须先安装相应的源码控制工具。
  • go clean,用来移除当前源码包和关联源码包里面编译生成的文件
  • go fmt,go强制了代码格式(比如左大括号必须放在行尾)使用go fmt命令,其实是调用了gofmt,而且需要参数-w,否则格式化结果不会写入文件。gofmt -w -l src,可以格式化整个项目。
  • go test,执行这个命令,会自动读取源码目录下面名为*_test.go的文件,生成并运行测试用的可执行
    文件。
  • go run,编译并运行Go程序
  • go tool,
  • go generate
  • godoc,

语言基础

  • 一些概念

    • 零值,go中的零值不是空值nil,而是默认值,对于整数与浮点数一般是0,字符串就是""
    • 全局的且以大写开头的变量与函数是public的,即可以在包外使用如:fmt.Print()
    • 数组(array)的定义:var arr [n]type
      • 数组的长度也是数组类型的一部分,即不同长度的数组是不同的类型。数组的长度不看变
      • go中数组的赋值使用的是pass by value,将赋值整个数组而非指针,这点与C不同
      • c := [...]int{4, 5, 6} //由编译器自动推测长度
      • b := [10]int{1, 2, 3} //只设定一部分,其他为默认值
      • easyArray := [2][4]int{{1, 2, 3, 4}, {5, 6, 7, 8}} //多维数组
      • array中的切片语法与pyton相似
    • 动态数组(slice)
      • 声明方式:var fslice []int //与array相比没有指定长度
      • slice是引用类型,可以将其看做opencv中的Mat,拷贝时默认为浅拷贝
      • slice := []byte {'a', 'b', 'c', 'd'}
      • slice对象中有几个内置成员函数:len、cap(最大容量)、append、copy(类似于Mat::clone)
    • 字典(map,与C++中的map相似)
      • 声明方式:var varable map[keyType]valueType
      • map和其他基本型别不同,它不是thread-safe,在多个go-routine存取时,必须使用mutex lock机制
      • map也是一种引用类型。
      • 自动推导的方式:rating := map[string]float32{"C":5, "Go":4.5 }
      • 使用示例:numbers["ten"] = 10 //赋值
      • csharpRating, ok := rating["C#"],map有两个返回值,第二个返回值,如果不存在key,那么ok为false,如果存在ok为true
    • make&new
      • new
        • new与C++中的关键字new类似,用于分配内存,但GO中没有堆栈之分,go中new也返回指针
        • go中的new将初始化内存
      • make
        • make只能创建內建类型(map、slice、channel),make返回的不是指针而是初始化了的对应类型的变量。如果上面三个类型的变量没有初始化则为nil,make返回的都已经初始化。
    • go的switch中的每个case语句自带break,与C有明显的差别
    • go中的函数声明
      • func funcName(input1 type1, input2 type2) (output1 type1, output2 type2)...return v1,v2...
      • 变量output1和output2不想声明也可以,直接就两个类型
      • 如果只有一个返回值且不声明返回值变量,那么可以省略包含返回值的括号
    • go中的函数变量
      • go中的函数也可以作为变量进行传递,C中只能传递函数指针
      • 函数类型的声明:type typeName func(input1 inputType1 , ...
    • go中的变参:func myfunc(arg ...int) {},变量arg是一个int的slice
    • go中的指针
      • 声明:var a *int
      • 星号与C中的功能时相同的,声明与解引用都是星号 *
      • 与C一致,go中使用 & 求变量的地址
    • defer关键字
      • 使用defer关键字修饰的语句将在函数返回前逆序执行,这与C++11中的lock_gurad思想类似,不过go中的defer语句是在函数返回语句之前执行。可以假设每个函数中都有一个defer栈,每一个出现的defer语句都将推入栈中,然后在返回前依次出栈执行。
    • init函数
      • init与main一样,不能有参数与返回值
      • 一个包里可以有任意多个init函数,但一般定义一个最好
      • 当一个包被导入时其中的包级常量与变量将被初始化(重复导入的包只初始化一次),然后init中将会被依次执行。最后系统将初始化main包中的变量然后执行main函数
  • 代码示例

    //说明当前文档所属的包,GO中包名和文件名可以不一样
    package main  //main包很特殊,表明当前文件是一个独立的执行入口包
    
    import(
    	"fmt"
    	"errors"
    	"./model" // 使用相对路径导入模块,亦可以使用绝对路径导入包
    	. "xxx"   // 可以不使用前缀使用包xxx中的成员
    	f "xxx"   // 为包xxx取个别名
    	_ "xxx"   // 引入包xxx但不使用其中的函数,仅仅调用了包中的init函数
    )
    
    func main(){ //go中的main是没有返回值与参数的
    	fmt.Println("你好!") //go默认使用utf8作为编码标准
    	
    	//变量定义,go中强制每个类型都有初始值
    	//var name type 
    	var a,b int = 1,2 //a b 都是int类型的变量,int型具体长度依赖编译器实现
    	//byte(uint8)、int、uint、int32(rune)、uint32,complex128
    	var c int64  //c 的长度固定为64位
    	//GO中各种类型之间不能进行操作与赋值,下面的操作将报错
    	//c := a + c
    	d := a  //:= 使用:=后变量的类型自动推导前面变量的类型,这种语法只能用于函数内
    	var e = b //这样也是自动推导e的变量类型
    	//可以在需要的地方使用 _ 作为占位符,但 _ 是不能作为正常变量使用的,f默认float64
    	//go中声明但没有使用变量将报错,故使用 _ 丢弃部分函数返回值
    	_,f := 1.0,2.0 
    	const g = "hello" //使用const关键字可自动推导类型 
    	var h bool //h默认为 false
    	var ( // 或 var ( 等
    		i int
    		pi float32
    		prefix = "go_"
    	)
    	//go中的字符串可以使用双引号("")或反引号(``)包含
    	str1,str2 := `hello`,"aworld" //使用``包含的字符串是raw字符串
    	//str[0] = 'm' //与python类似,go中的字符串默认常量,无法更改。可以改成[]byte
    	str1 = str1+str2[1:] //与python类似,go中的字符串可以进行切片操作
    	err := errors.New("this is a error")
    	if err != nil{ //go中有一个error类型,专门用于处理错误信息
    		fmt.Print(err)
    	}
    	//go中的关键字iota用于声明枚举变量时使用
    	//除非被显式设置为其它值或iota,每个const分组的第一个常量被默认设置为它的0值
    	//第二及后续的常量被默认设置为它前面那个常量的值,如果前面那个常量的值是iota,
    	//则它也被设置为iota。
    	const (
    		x = iota //x == 0,默认开始值为0
    		c = "c"
    		y = iota //y == 1
    		z  		 //z == 3
    	)
    	const w = iota //w == 0,因为iota每遇见一个const关键时都会重置为0
    	
    	//流程与函数
    	if x := fun();x>0{//if的条件判断中可以声明一个变量,也可以没有
    		...
    	} else{
    		...
    	}
    	for expression1; expression2; expression3 {
    		//...
    	}
    	for sum < 1000 {//go中没有while关键,其功能使用for实现
    		sum += sum
    	}
    	for _, v := range map{
    		fmt.Println("map's val:", v)
    	}
    
    }
    
    //go中函数的声明顺序不像C那么严格,这点go与python类似:先扫描文档,后找依赖关系
    //a的类型为离其最近的类型
    func max(a, b int) int {
        if a > b {
            return a
        }
        return b
    }
    
    //如果在返回参数列表中有变量名,可以使用不带参数的返回值语句返回这两个参数
    func SumAndProduct(A, B int) (add int, Multiplied int) {
        add = A+B
        Multiplied = A*B
        return
    }
    
posted @ 2017-11-08 10:02  jiahu  阅读(558)  评论(0编辑  收藏  举报