Go总结(2)

struct

go中struct结构默认字段都会有零值,故不能用nil来判断struct是否为空,可经过额外的字段来判断struct是否填充或为空web

type Demo struct{
    ready bool

    name string
    //其余字段
}

在初始化的时候必须将ready设置为true编程

var d Demo
if !d.ready{
    //do stuff
}

Web工做方式

  • Go经过ListenAndServer来创建web服务器,底层是初始化一个server对象,而后调用net.Listen("tcp",addr)来监听端口。
  • 调用srv.server(net.Listener)函数来处理接收客户端请求。函数里面为一个for{},首先经过accept接受请求,接着建立一个Conn,最后单独开一个goroutine取执行:go c.server()
  • 用户的每一次请求都是一个新的goroutine去执行。
  • conn经过解析requestc.readRequest()获取相应的handler := c.server.Handler,它本质是一个路由器,经过它来匹配url跳到对应的handle函数。
  • 可经过`http.HandleFunc("/",sayhelloName)来注册请求的路由规则。

OS获取环境变量

os.getenv()获取环境变量获取不到最新设置的环境变量,最新设置的须要从新启动电脑获取数组

基本类型

这两天在搞反射,看到Go的基础数据类型那么多,int,int32,int64都有,并且运算过程当中还须要转换,因此抽空看了些博客以及官方文档。
  • int跟uint服务器

    • 有符号:int8,int16,int32,int64
    • 无符号:unit8,unit16,unit32,uint64
    • int和unit取决于操做系统,在32位系统就是32字节,在64位系统就是64字节
    • int跟int32不是相同的类型,虽然在特定的场景下它们大小相同,可是在运算过程当中须要转换
    • byte是unit8的别名,rune是int32的别名
  • 浮点类型为float32和float64app

    • 浮点类型在运算过程当中可能存在精度丢失的状况
  • stringtcp

    • 字符串是不可变的,一旦建立,就不能改变字符串的内容
    • 可使用内置函数len来发现s的长度,若是字符串为常量,则length是编译时常量。
    • 字符串的字节能够经过索引来获取,可是取元素的地址是非法的,即&s[i]是无效的。

反射

反射在计算机中是程序检查本身结构的一种能力,尤为是经过类型,它是元数据编程的一种方式,也是混乱的重要来源

每一个语言的反射模型都不一样(不少语言根本不支持它)函数

Type And interface

由于反射是创建在类型系统上,让咱们先回顾一下Go中的类型。post

Go是静态类型语言,每一个变量都有一个静态类型,即在编译时就已知被固定上一种类型:int, float32, &MyType, []byteui

type MyInt int

var i int
var j MyInt

变量i和j具备不一样的静态类型,虽然他们具备相同的底层类型,但若是没有转换,则没法将他们分配给彼此。url

interface能够存储任何具体的值,interface包括:

  • 变量包括(type,value)两部分,这也是为何nil != nil的缘由
  • type包括static type和concrete type,static type是编辑时就看到的类型,而concrete type是runtime看到的类型

反射就是创建在类型之上的,Golang的指定类型的变量的类型是静态的(也就是指定int、string这些变量,它的type是static type),在建立变量的时候就已经肯定,反射主要于Golang的interface有关(它的类型是concrete type),只有interface类型才有反射之说。

API

如下是一些API

reflect:
    TypeOf(interface{}) Type : 返回接口中保存值的类型,i为nil值返回nil
    ValueOf(interface{}) Value : 返回一个初始化为i接口保管的具体值的Value,但i为nil时返回Value零值
    New(Type) Value:返回一个指向类型为Type的新申请的零值的指针。

Type:
    Kind():返回该接口的具体类型
    Name():返回类型名
    Elem():返回该类型的元素类型,若是Kind不是Array,Chan,Map,Slice,Ptr会panic

Value:
    Append(s Value,x ...Value) Value: s需为切片类型的Value值,x需为s的元素类型的Value值,将x复制给s而且返回s
    Type():返回v持有的类型的Type表示
    Elem() Value:返回v持有的接口或者指针保管值的Value封装,若是v的Kind不是interface或者Ptr将会panic
    Kind():同上一致
    CanSet():判断v持有的值是否能更改,只有当Value持有值为Ptr而且为共有类型时,它才能够被修改。
    Set(x Value):将v的持有值修改成x的持有值
    SetInt(x Int64)
    SetString(s string)
    ....

更多的可参考官方文档:https://go-zh.org/pkg/reflect/#Value.Convert

反射讲得比较好的一篇文章:http://www.javashuo.com/article/p-epkjfqjn-kw.html

Go运行时

尽管Go编译器产生的是本地可执行代码,这些代码仍旧运行在Go的runtime(这部分的代码能够在runtime包中找到)当中,这个runtime相似虚拟机,它负责管理包括内存分配、垃圾回收、栈处理、goroutine、channel、slice、map和reflection等等。

Interface

Go中的interface并非显示实现的,这就致使,一个方法接收的类型为IPerson,可是虽然个人Student对象已经实现了IPerson,可是仍是不要在经过方法去new实现返回IPerson对象

type Student struct{
    name string
    age int
}

func newIPerson(name string,age int) IPerson{
    return Student{
        name : name,
        age : age,
    }
}

切片

  • make([]int,l,c)l为长度,c为容量,不传c则容量等于长度
  • 底层仍是数组,经过len()获取长度,cap()获取容量
  • append以后返回的是一个新的切片
  • 扩容:

    • capacity小于1000时,两倍扩容
    • capacity大于1000时,增加因子为1.2525%扩容
  • 赋值:将一个切片赋值给另外一个切片可指定索引

    • 第一个索引:指定切片的头部
    • 第二个索引:指定切片长度的尾部
    • 第三个索引:限制切片的容量

参考下面代码:

a := []int{1, 2, 3, 4, 5}
b := a[1:]
c := a[:4]
d := a[1:4]
e := a[2:3:4]
fmt.Println("a", len(a), cap(a))
fmt.Println("b", len(b), cap(b))
fmt.Println("c", len(c), cap(c))
fmt.Println("d", len(d), cap(d))
fmt.Println("e", len(e), cap(e))

//打印结果
a 5 5
b 4 4
c 4 5
d 3 4
e 1 2
  • for-range返回的是每一个元素的副本,而不是引用
  • 切片在函数件传递仍是以值传递的方式传递,因为切片的尺寸很小,在函数间复制和传递切片的成本也很低。在64位结构的机器上,一个切片须要24个字节,指针字段8字节,长度和容量分别须要8字节,因为与切片关联的数据包含在底层数组里面,不属于切片自己,因此将切片复制给人以数组时对底层数组大小都不会有影响。

clipboard.png

相关文章
相关标签/搜索