Skip to content

cnych/golearn

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

23 Commits
 
 
 
 
 
 

Repository files navigation

learn golang

IDE

推荐使用Gogland或者IntelliJ IDEA安装golang插件,其他的sublime text或者vs code都可以,选择自己熟悉的开发工具就OK~

代码结构

  1. scorpio工程是核心代码,与业务相关的所有代码都放置在该工程下面
  2. starjazz-go工程是项目用到到所有公共代码,包括第三方包(包括用go get命令安装)都放置在该工程下面

安装

  1. 进入scorpio目录,执行setup-gopath.sh脚本,该脚本会把当前目录和starjazz-go项目设置为gopath
  2. 提交代码之前先手动执行format-src.sh脚本,该脚本会用golang的标准方式格式化代码
  3. 也可以直接在git本地的pre-commithook文件中加上上面格式化的脚本,避免每次手动执行

运行

  1. 可以在scorpio根目录中新建一个bin文件夹
  2. 进入bin文件夹,执行命令go build scorpio/mathapp
  3. bin目录下面会生成一个mathapp的可执行文件,执行命令./mathapp即可得到运行结果
  4. 也可以直接在scorpio根目录下面直接执行命令go run src/scorpio/mathapp/main.go得到运行结果

学习

指针

代码路径:pointers.go

Go 具有指针。 指针保存了变量的内存地址。

类型 *T 是指向类型 T 的值的指针。其零值是 nil

    var p *int

& 符号会生成一个指向其作用对象的指针。

    i := 42
    p = &i

* 符号表示指针指向的底层的值。

    fmt.Println(*p) // 通过指针 p 读取 i
    *p = 21         // 通过指针 p 设置 i

这也就是通常所说的“间接引用”或“非直接引用”。

C 不同,Go 没有指针运算。

结构体

代码路径:structs.go

一个结构体(struct)就是一个字段的集合。

(而 type 的含义跟其字面意思相符。)

结构体字段使用点号来访问。

结构体字段可以通过结构体指针来访问,通过指针间接的访问是透明的。

数组

代码路径:array.go

类型[n]T是一个n个类型为T的值的数组。

表达式

    var a [10]int

定义变量a是一个有10个整数的数组。

数组的长度是其类型的一部分,因此数组不能改变大小。

slice

一个slice会指向一个序列的值,并且包含了长度信息。

[]T是一个元素类型为Tslice

对slice切片

slice可以重新切片,创建一个新的slice值指向相同的数组。

s[lo:hi]:表示从lohi-1slice元素,含两端。

因此s[lo:lo]是空的,而s[lo:lo+1]有一个元素。

构造slice

slice由函数make创建。这会分配一个零长度的数组并且返回一个slice指向这个数组:

    a := make([]int, 5) // len(a)=5

为了指定容量,可以传递第三个参数到make

    b := make([]int, 0, 5) // len(b)=0, cap(b)=5

    b = b[:cap(b)]  // len(b)=5, cap(b)=5
    b = b[1:] // len(b)=4, cap(b)=4

slice的零值是nil,一个nil的slice长度和容量是0

向slice添加元素

slice添加元素是一种常见的操作,Go提供了一个内建的append函数。

 func append(s []T, vs ...T) []T

append的第一个参数s是一个类型为T的数组,其余类型为T的值将会添加到slice上。 append的结果是一个包含原slice所有元素加上新添加的元素的slice。 如果s的底层数组太小,而不能容纳所有的值时,会分配一个更大的数组。返回的slice会指向这个新分配的数组。

参阅slice文章:使用和内幕

interface

代码路径:interfaces.go

接口是什么?

Go语言没有类和几成的概念。但是Go语言有非常灵活的接口概念,通过它可以实现很多面向对象的特性。 接口提供了一种方式来说明对象的行为。 接口定义了一组方法集,但是这些方法不包含(实现代码):它们没有被实现(它们是抽象的)。接口里也不能包含变量。 有的时候,也会以一种稍微不同的方式来使用接口这个词:从某个类型的角度来看,它的接口指的是:它的所有导出方法,只不过没有显式地为这些导出方法额外定一个接口而已。

接口嵌套接口

一个接口可以包含一个或者多个其他的接口,这相当于直接将这些内嵌接口的方法列举在外层接口中一样。

比如接口File包含了ReadWriteLock的所有方法,它还额外有一个Close方法。

type ReadWrite interface {
    Read(b Buffer) bool
    Write(b Buffer) bool
}

type Lock interface {
    Lock()
    Unlock()
}

type File interface {
    ReadWrite
    Lock
    Close()
}

类型转换

一个接口类型的变量varI中可以包含任何类型的值,必须有一种方式来检测它的动态类型,即运行时在变量中存储的值的实际类型。 在执行过程中动态类型可能会有所不同,但是它总是可以分配给接口变量本省的类型。通常我们可以使用类型断言来测试在某个时刻varI是否包含类型T的值:

    v := varI.(T)  // unchecked type assertion

varI 必须是一个接口变量,否则编译器会报错:invalid type assertion: varI.(T) (non-interface type (type of varI) on left)

类型断言可能是无效的,虽然编译器会尽力检查转换是否有效,但是它不可能预见所有的可能性。如果转换在程序运行时失败会导致错误发生。更安全的方式是使用以下形式来进行类型断言:

    if v, ok := varI.(T); ok {  // checked type assertion
        Process(v)
        return
    }
    // varI is not of type T

如果转换合法,vvarI转换到类型T的值,ok会是true;否则v是类型T的零值,okfalse,也没有运行时错误发生。

应该总是使用上面的方式来进行类型断言。

grpc

参考资料: grpc grpc-api

gRPC是一个高性能、通用的开源RPC框架,其由Google主要面向移动应用开发并基于HTTP/2协议标准而设计,基于ProtoBuf(Protocol Buffers)序列化协议开发,且支持众多开发语言。 gRPC提供了一种简单的方法来精确地定义服务和为iOSAndroid和后台支持服务自动生成可靠性很强的客户端功能库。客户端充分利用高级流和链接功能,从而有助于节省带宽、降低的TCP链接次数、节省CPU使用、和电池寿命。 我们可以从这里http://www.grpc.io/blog/principles gRPC的动机和设计原则。

gRPC

Releases

No releases published

Packages

No packages published