golang基础之一

1、第一个go程序

package main

import (
       "fmt"
)

func main(){
       fmt.Println("hello world")
}

对于代码的解释html

若是是为了将代码编译成一个可执行程序,那么package必须是main
若是是为了将代码编译成库,那么package则没有限制
go中全部的代码都应该隶属一个包python

fmt 是go的一个系统库linux

fmt.println()则能够打印输出golang

若是想要运行程序:go run 程序名并发

在一个可执行程序只有一个main函数函数

关于注释高并发

单行注释://
多行注释:/* */单元测试

2、go语言初识

关于定义一个变量测试

var 变量名 变量类型
变量名 = 值ui

这里须要注意:go语言中定义的变量必须被用到,不然会报错
同时定义变量和赋值能够一步完成经过: 变量名 := 值

定义一个函数

若是咱们要定义一个函数,咱们先看下面求和的例子:

func add(a int,b int) int {
    var sum int
    sum = a + b
    return sum
}

这里咱们须要知道,下面这种格式是被严格要求的,包括第一行的大括号不能放到下一行
func 函数名(参数1 参数1类型,参数2 参数2类型) 返回值类型 { 

}

3、golang语言特性

垃圾回收

内存自动回收,不须要开发人员管理内存
开发人员专一业务实现
只须要new分配内存,不须要释放

自然高并发

  • 从语言曾元支持并发,很是简单
  • goroute,轻量级线程,建立成千上万goroute成为可能
  • 基于CSP模型实现

关于高并发的一个简单演示:

import (
    "fmt"
    "time"
)


func test_print(a int){
    fmt.Println(a)
}


func main(){
    for i:= 0;i < 100; i ++ {
        go test_print(i)
    }
    time.Sleep(time.Second)
}

在实现高并发的时候只须要在调用的函数前面加上go,就表示开启了并发

若是在for循环的外面不加上time.Sleep(time.Second),就会发现会少打印了,这是由于当主程序运行完以后,并不会等待线程,因此程序直接终止

channel管道

相似linux中的pipe
多个goroute之间经过channel进行通讯
支持任何类型

package main

import (
    "fmt"
)

func test_pipe(){
    pipe := make(chan int,3)
    pipe <- 1
    pipe <- 2
    pipe <- 3

    fmt.Println(len(pipe))
}

func main(){
    test_pipe()
}

上述代码的解释:
pipe := make(chan int,3) 这里是定义一个管道pipe,go是强类型语言,因此这里声明一个管道变量pipe须要经过有三个参数,chan表示是管道,int表示管道类型,3表示管道容量
经过len(pipe)能够查看管道的的长度

若是想要从管道里获取数据
t1 :=<- pipe 这个写法等同于
var t1 int
t1 = <- pipe
fmt.Println(t1)
管道遵循的原则是先进先出,因此第一个获取的值是1

小结:若是想要给管道放入值:定义的管道pipe < - 要存入的内容
若是想要从管道中获取值:变量名 =<- 定义的管道pipe

这里强调一下go中package包的概念,一个包里的变量,在这个包里是均可以访问,可是在包以外也是有权限限制是否能够访问到,若是一个变量在一个包里是大写的,在其余包里就能够访问到,若是是小写的其余包里则访问不到。相似其余语言中的public和private

多返回值

一个函数能够返回多个值

package main

import "fmt"

func calc(a int,b int) (int,int ){
    sum := a + b
    avg := sum / 2
    return sum,avg
}

func main(){
    sum,avg := calc(100,200)
    fmt.Println(sum,avg)
}

关于须要传入多个参数的时候是用括号括起来单个的状况下通常不用括号括起来,直接int,而这里是返回两个则须要 (int,int)表示返回两个整数类型值

若是有多个返回值,可是我只想返回一个值,是经过下划线方式实现,则上述代码改成:

func main(){
    sum,_ := calc(100,200)
    fmt.Println(sum)
}

4、包的概念

  • 和python同样,把相同功能的代码放到一个目录,称之为包
  • 包能够被其余包引用
  • main包是用来生成可执行文件,每一个程序只有一个main包
  • 包的主要用途是提升代码的可复用性

关于main包中的main函数,go程序通过编译以后,运行该程序,会将编译好的二进制文件加载到内存中,会首先调用main函数,因此main函数是程序的入口函数,即必须有package main

关于包,是咱们能够把一些经常使用的功能封装到包中,这个时候包中的每一个go文件的开头则不须要package main,而是package 自定义名字,这个自定义名字是根据这个包的功能进行命名

go源码按package进行组织,而且package要放到非注释的第一行
一个程序只有一个main包,一个包中只能有一个main函数,不能重复定义
main函数是程序的执行入口
没有被引用的变量,编译的时候会报错

 

go的目录规范

这里举一个简单的例子:若是咱们在创建一个go_project目录,一般在这个目录下咱们会建立以下目录
src 存放不一样的项目代码
bin 存放编译后的可执行程序
vender 存放引用的第三方库
pgk 存放静态库

 

咱们的go环境变量中的GOPATH通常会设置为:
(我这里是路径是/Users/myname/learngo)
export GOPATH=/Users/myname/learngo

go的编译

若是咱们写好了go的代码文件,咱们若是测试运行能够经过:
go run 快速执行go文件
go build 编译程序,生成二进制文件
go install 安装可执行文件到bin目录下

基本命令:
go test执行单元测试或压力测试
go env 显示go相关的环境变量
go fmt 格式化源代码

咱们经过下面例子理解这个编译命令的使用:

例子一

我在/Users/myname/learng/src/go_dev/day01/hello目录下写了一个hello程序
如今把这个hello程序进行编译

咱们在go_project目录下执行的编译命令,若是不指定编译生成的文件会直接将编译文件生成在当前目录即go_project目录下

这里须要解释的是go build 后面的路径go build go_dev/day01/hello 
咱们从目录结构能够看出,go_dev的上一级目录src目录并无写,这是由于go编译的时候,会自动去GOPATH下的src目录里去找,因此这里是不须要写,同时编译的路径的最后咱们只写到hello目录而不是hello.go文件

例子二

咱们在/users/myname/go_project/src/go_dev/day01/ 目录下创建一个goroute目录
并在goroute目录下创建两个go文件,main.go和goroute.go文件

main.go文件的代码为:

package main
import (
       "time"
)

func main(){
        for i := 0; i < 100; i++ {
            go test_goroute(i)
        }
        time.Sleep(time.Second)
}

goroute.go文件的代码为:

package main

import "fmt"

func test_goroute(a int){
    fmt.Println(a)
}

这样咱们编译的时候只须要在go_project目录下执行:
go build go_dev/day01/goroute
这样就会再go_project目录下生成一个可执行文件goroute

例子3
仍是在/users/myname/go_project/src/go_dev/day01/下创建一个goroute_test目录
在goroute_test目录下创建calc目录和main目录
同时在calc下创建一个sum.go文件,在main目录下创建一个main.go文件

sum.go文件代码以下:

package calc


func Add(a int,b int,c chan int){
    sum := a + b
    c <- sum
}

这里有个地方须要注意这里咱们的sum.go是做为包写的,因此咱们开头是:package calc,即package+sum.go的所在上级目录,而且是sum中定义的函数名首字母要大些(这个是必须的)这里实际上是由于
咱们定义的包都是要被外部的其余包调用,即咱们这里定义的sum.go是要被其余包调用,这个时候只有首字母大写才能被其余包调用到

main.go文件代码以下:

package main

import (
    "fmt"
    "go_dev/day01/goroute_test/calc"
)

func main(){
    pipe := make(chan int,1)
    calc.Add(100,200,pipe)
    res :=<- pipe
    fmt.Println(res)
}

此次咱们编译的时候指定编译文件生成的目录路径,命令以下:
go build -o bin/goroute_test go_dev/day01/goroute_test/main

 

关于单元测试例子:
单元测试的代码文件的名字格式必须是:*_test.go
例如我要写关于calc.go文件的单元测试
新建一个文件命名为:calc_test.go

这里须要知道的是开头的calc的名字并非强制的,可是为了方便测试哪一个代码文件,开头就以那个文件开头,下面是一个例子代码:

 1 package calc
 2 
 3 import (
 4     "testing"
 5 )
 6 func TestAdd(t *testing.T){
 7     var sum int
 8     sum = Add(5,6)
 9     if sum != 11{
10         t.Fatalf("add is not right,sum:%v expected:11",sum)
11     }
12     t.Logf("add is Ok")
13 }

在代码中咱们定义函数时候函数的名字也须要以Test开头
上述测试文件执行结果:

 1 bogon:calc myname$ go test
 2 PASS
 3 ok      go_dev/01/calc  0.007s
 4 bogon:calc myname$ go test -v
 5 === RUN   TestAdd
 6 --- PASS: TestAdd (0.00s)
 7     calc_test.go:12: add is Ok
 8 PASS
 9 ok      go_dev/01/calc  0.007s
10 bogon:calc myname$

Go的结构开发规范 

好的代码规范是很是重要的,这样当你看别人代码或者别人看你的代码的时候就能很清楚的明白,下面是结构规范

// 当前程序的包名
package main

//导入其余的包
import "fmt"

//常量的定义
const PI=3.14

//全局变量的声明和赋值
var name = "gopher"

//通常类型声明
type newType int

//结构的声明
type gopher struct{}

//接口的声明
type golang interface{}

//由main函数做为程序入口点启动
func main(){
    fmt.Println("Hello world! 你好世界")
}

 转自https://www.cnblogs.com/zhaof/p/6962813.html

相关文章
相关标签/搜索