golang学习

第一天上班,因为公司马上要搬家,新电脑的话就安置在新场地了,原本golang在linux(Ubuntu 14.04 据说16容易崩溃)上用比较好。但是由于条件艰苦,还是先简单看语法内容吧。

首先我为什么要学习go语言,实习内容是做区块链的开发,Go 语言被设计成一门应用于搭载 Web 服务器,存储集群或类似用途的巨型中央服务器的系统编程语言。 

Go 语言在用于高性能分布式系统开发中,无疑比大多数其它语言有着更高的开发效率。此外,它提供了海量并行的支持,这对于游戏服务端的开发而言也是不错的选择。同时go最终生成的是一个 可执行文件,不管你的程序依赖多少库,都会被打包进行,生成一个可执行文件,所以相比java庞大的jar库来说,他的部署非常方便,执行运行这个可执行文件就好了。

 

Go开发环境配置:

访问 Golang官网,下载指定平台的安装包,目前支持WindowsMacOS XLinux 和 FreeBSD 四个平台,这里我们以Windows为例:

1.Windows下的安装:

安装包 go1.10.3.windows-amd64.msi 

资源地址: 

  • 可以到这里下载安装包:Golang中国 或者 官网下载

  • 检查版本: 
    直接打开cmd命令行,输入一下指令查询安装Go的版本:

    C:\Users\Administrator>go version
    go version go1.10.3 windows/amd6

2.Linux下的安装:

  • 下载源码包:go1.10.3.linux-amd64.tar.gz
  • 解压到/usr/local目录:tar -C /usr/local -xzf go1.10.3.linux-amd64.tar.gz
  • /usr/local/go/bin目录添加到Path环境变量中:export PATH=$PATH:/usr/local/go/bin

第一行代码:

 

  • Tour编辑器: 
    假如只是前期的语法学习,可以考虑先不安装开发环境,可以直接在 Golang官网 上的网页内嵌 Tour编辑器 中编写代码和运行: 
    在编辑器中编写如下代码:

    package main
    
    import "fmt"
    
    func main() {
        fmt.Println("Hello world!")
    }

    运行结果: 

  • 本地运行: 
    也可以在本地创建一个hello.go文件,内容与上述一致,然后在命令行定位到创建.go文件的目录下,执行go run (.go文件名)

    E:\Go\Projects>go run hello.go
    Hello world!

    此过程会将.go源码编译成二进制文件,但是编译结果不会保存到本地,可以go build实现此过程,编译结果hello.exe会保存到本地,可以直接在命令行运行:

    E:\Go\Projects>hello.exe
    Hello world!
  • 源码解析:

    • package:是一个关键字,定义一个包,和Java中的Package一样,用于模块化编程;
    • import:也是一个关键字,用于引入包,与Java的import一样,引入包之后可以使用其中的功能;
    • fmt:Go语言的一个自带功能包;
    • main():主函数,也是程序执行的入口;
    • fmt.Println:用于输出一段字符串。

    不难发现Go语言与Java的关键字、函数和包等很相似,但是,Go语言不需要以 ; (分号)符号结尾,一行代表一个语句结束。

 

Go基本语法:

1.基本数据类型:

数值类型说明
bool布尔
string字符
int,int8,int16,int32,int64int长度与平台相关
uint,uint8,uint16,uint32,uint64uint长度与平台相关
uintptr同指针,32位平台为4字节,64位八字节
byte等价于uint8
rune等价于uint32,单个unicode字符
float32,float64 
complex64,complex128复数类型, value = 3.2+12i

2.数值定义:

Go语言最独特的就是:声明变量或者常量时,类型表示写在变量或者常量名称之后。

  • 常量:

    • 显式定义
    const a int = 1
    • 隐式定义
    const a = 1

    可以进行多个相同或不同类型的声明:

    const a, b, c = 1, false, "str" //多重赋值
  • 变量:

    var s string = "hehe"

    声明后若不赋值,使用默认值:

    int a

    假如输出a结果,则为int默认值0。还可以同时对多个相同或不同类型的变量进行声明:

    var e, f = 123, "hello"

    也有一种简化的声明方式,不需显示声明变量类型也省去了var,变量的类型由go根据值推导出来:

    s := "hehe"

有兴趣的还可以了解一下值类型引用类型的区别。

3.操作符:

  • 赋值: =,:=
  • 数值运算: +(相加),-(相减),*(相乘),/(相除),%(求余),++(自增),--(自减)
  • 比较运算: >,<,==,>=,<=,!=
  • 逻辑运算: &&,||,!
  • 位运行: >>,<<,^,&(与),|(或),^x(取反)
  • 其他: &(变量存储地址),*(指针变量)

其中有两个比较特殊的操作符:

特殊操作符说明
:=无需指定类型即可赋值:i, j := true, "hello"
_空白标识符,可以赋任意值的空对象:_ = "string"

空白标识符 _ 也被用于抛弃值,如值 5 在:_, b = 5, 7 中被抛弃。 
_ 实际上是一个只写变量,你不能得到它的值。这样做是因为 Go 语言中你必须使用所有被声明的变量,但有时你并不需要使用从一个函数得到的所有返回值。

4.大小写标记访问权限:

在go中不能随便使用大小写的问题,是因为大小写具有特殊意义,在go中,大写字母开头的变量或者函数等是public的,可以被其他包访问;小写的则是private的,不能被其他包访问到。这样就省去了public和private声明的烦恼,使代码变的更简洁。

5.关键字:

关键字作用
package代码所属包
import导入依赖包,不能导入不使用的包
main主函数入口,无参数无返回值,命令行参数保存在os.Args中
func函数声明
go开启协程(并发核心)
map字典类型, map[string]bool
delete专用来删除字典中的元素
chan通道,协程通信核心
select同时读取多个chan的信息
close用来关闭通道
make用来创建chan或map
type类型定义,定义任意需要的类型
structC中的结构体,但可以定义方法以实现类功能
interface接口类型,用来定义接口
new新建对象, 并获得它的指针
range类似python的range,配合for遍历列表、数组或map的元素
defer自动关闭资源,退出代码体(一般是函数)时执行
errorerror接口,只要实现Error()string方法就是一个error接口
panic抛出异常,如果不用recover捕获则会终止程序
recover捕获panic异常,防止程序终止,与recover结合

6.注释:

Go 程序的代码注释与 C++ 保持一致,主持:块注释 与 行注释

  • 块注释:

    /*
    块注释
    */
  • 行注释:

    // 行注释

7.流程控制:

  • 条件:

    条件语句说明
    ifif 语句 由一个布尔表达式后紧跟一个或多个语句组成。
    if…elseif 语句 后可以使用可选的 else 语句, else 语句中的表达式在布尔表达式为 false 时执行。
    if 嵌套你可以在 if 或 else if 语句中嵌入一个或多个 if 或 else if 语句。
    switchswitch 语句用于基于不同条件执行不同动作。
    selectselect 语句类似于 switch 语句,但是select会随机执行一个可运行的case。如果没有case可运行,它将阻塞,直到有case可运行。
    • if

      if i>0 {
      //条件执行内容
      }

      相比于其他语言,Go语言的条件判断语句不需要小括号

      // 特殊用法, 判断语句中可以初始化变量
      if i:=4;i>0{
      fmt.Println("i = ",i)
      }
    • switch,case

      switch i {
      case 0:
      // ...
      case 1:
      // ...
      default:
      // ...
      }

      Go语言的 switch 不需要 break 来跳出一个 case

    • select 
      可以看做是专用于通信的switch语句,每一个case必须是一个通信操作,要么是发送要么是接收。select执行逻辑:随机执行一个可运行的case。如果没有case可运行,它将阻塞,直到有case可运行。一个默认的子句应该总是可运行的。

      select {
      case communication clause  :
         statement(s);      
      case communication clause  :
         statement(s); 
      /* 你可以定义任意数量的 case */
      default : /* 可选 */
         statement(s);
      }

      执行select的语法大致如下:

      • 每个 case 都必须是一个通信
      • channel 表达式都会被求值
      • 所有被发送的表达式都会被求值
      • 如果任意某个通信可以进行,它就执行;其他被忽略。
      • 如果有多个 case 都可以运行,select 会随机公平地选出一个执行。其他不会执行。
      • 否则: 
        1.如果有 default 子句,则执行该语句。 
        2.如果没有 default 字句,select 将阻塞,直到某个通信可以运行;Go不会重新对channel或值进行求值。
  • 循环:

    循环语句说明
    for重复执行语句块
    for嵌套在 for 循环中嵌套一个或多个 for 循环

    Go语言中的for循环与Java、C#等的区别就是三个由 ;(分号)分开的组成部分不需要小括号括起来:

    for i := 0; i < 10; i++ {
    sum += i
    }

    Go语言中没有其他语言中while的用法,for 在Go语言中可以当做 while 来用:

    sum := 1
    //循环条件
    for sum < 1000 {
    sum += sum
    }
    //死循环
    for {// 无退出条件,变成死循环
    }
  • 其他: 
    在Go语言中,同样可以使用breakcontinuegoto来控制流程:

    控制语句说明
    break经常用于中断当前 for 循环或跳出 switch 语句
    continue跳过当前循环的剩余语句,然后继续进行下一轮循环
    goto将控制转移到被标记的语句。

    例如goto,需要用一个文本来标志某个语句(写在该语句前面):

    goto label
    ..
    .
    label: statement

    label 就是用来标志的文本,statement 是一个普通的Go语句,goto label执行之后,程序将调到 statement 然后顺序往下执行。

8.函数:

Go语言中定义一个函数的格式如下:

func 方法名称([传入参数表]) [返回结果数据类型]{
    //函数体
}

上面使用[]符号括起来的部分表示 非必须 的,可根据使用情况决定是否可以不写,例如无需传入参数时,传入参数列表可以省略。注意:传入的参数列表中形式参数定义的格式也是:变量名在前,变量类型在后

  • 普通用法:

    package main
    
    import "fmt"
    
    func main(){
        PrintSth(1,2)
        sum := 0
        sum = mSum(10,20)
        fmt.Println("sum = ",sum)
    }
    
    func PrintSth(x,y int){
        fmt.Println("x = ",x,";y = ",y)
    }
    
    func mSum(x,y int) int{
        return x+y
    }
  • 返回多个值: 
    例如定义一个值互换的方法:

    //定义函数
    func swap(x, y string) (string, string) {
    return y, x
    }
    //调用函数
    a,b := swap("a","b")
  • 函数作为值: 
    定义函数的时候,也可以将函数声明为一个函数变量,调用的时候用函数变量替换函数真是名称来调用即可:

    /* 声明函数变量 */
    getSquare := func(x float64) float64 {
        return x*x
    }
    
    /* 使用函数 */
    fmt.Println(getSquare(3))
  • 闭包: 
    闭包,是匿名函数(一个“内联”语句或表达式)的一种声明方式,好处就是可以直接使用函数内的变量不必声明:

    //没调用一次getSequence,i就自增1
    func getSequence() func() int {
    i:=0
    return func() int {
       i+=1
       return i
    }
    }

    函数的返回结果是另一个函数。

  • 方法: 
    与函数略有不同,方法声明时会指定其所附的是命名类型或结构类型的一个值或者是一个指针,所有给定类型的方法属于该类型的方法集。例如:

    //定义结构体
    type Circle struct {
    radius float64
    }
    //此属于 Circle 类型对象中的方法
    func (c Circle) getArea() float64 {
    //c.radius 即为 Circle 类型对象中的属性
    return 3.14 * c.radius * c.radius
    }
    //调用
    main(){
    var c Circle
    c.radius = 1
    fmt.Println("Area of c = ", c.getArea())
    }

9.指针:

  • 指针变量: 
    一个 指针变量 可以指向任何一个值的内存地址,使用指针前需要声明,声明格式如下:

    var var_name *var-type

    var_name 是变量名,var-type 是指针类型,例如:

    var ip *int        // 此指针只能指向整型
  • 使用步骤: 
    创建指针变量,为指针赋值(如:指向变量),输出结果:

    var a int = 1
    //创建指针变量
    var ptr *int
    //指针赋值(指向变量a的地址)
    ptr = &a
    /* 指针变量的存储地址 */
    fmt.Printf("ptr 变量储存的指针地址: %x\n", ptr )
    /* 使用指针访问值 */
    fmt.Printf("*ptr 变量的值: %d\n", *ptr )
  • 取址符: 
    Go语言中,使用 & 作 取址符,假如放在变量前可以返回相应变量的内存地址:

    var a int = 1
    fmt.Printf("变量的地址: %x\n", &a  )

    输出结果:

    变量的地址: c0420382a0
  • 空指针: 
    Go语言中的空指针是 nil ,表示没有分配到任何变量,判断指针是否为空指针:

    //声明指针,不赋值
    var ptr *int
    if ptr == nil{
    //条件执行块
    }

10.结构体:

以关键字 type 和 struct 来一起声明一个结构体,格式如下:

type structure_variable_type struct{
    member menberType
    member menberType
    ...
}

其中 structure_variable_type 是当前定义结构体的名称,创建结构体操作:

variable_name := structure_variable_type(value1,value2,...)

例如:

//定义
type Info struct{
    id int
    name string
}
//声明
var mInfo Info
//赋值
mInfo.id = 1
mInfo.name = "linsh"

11.包的使用:

每个Go程序都是由包组成的,其中程序运行入口包为 main ,通常包名与导入目录路径最后一级目录名称一致。例如:导入“math、rand”包,这个包必然是以 package rand 语句开始的。

  • 导入包: 
    以 import 关键字来实现包的导入,有两种格式:

    • 多个导入语句:

      import "fmt"
      import "math"
    • “打包”导入:

      import (
      "fmt"
      "math"
      )

    使用第二种方式导入包更为方便。

  • 导出命名: 
    在Go编程中,某个包中 使用首字母大写的名称定义的属性或者方法可以被导入了此包的脚本调用,相当于是开放了访问权限,例如:这里我们定义了一个 ··Test·· 包,然后再 main 包中引入此包并调用其导出方法:

    package Test
    
    func SetName(_name string){
    
    }
    
    func setName(_name string){
    
    }

    在 main 中先 import Test,然后只能调用 SetName 函数而不能调用 setname

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值