golang 数组 最后一个_Golang总结(2)

Web工作方式

  • Go通过ListenAndServe来建立web服务器,底层是初始化一个server对象,然后调用net.Listen("tcp",addr)来监听端口。
  • 调用srv.serve(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和float64
    • 浮点类型在运算过程中可能存在精度丢失的情况
  • string
    • 字符串是不可变的,一旦创建,就不能改变字符串的内容
    • 可以使用内置函数len来发现s的长度,如果字符串为常量,则length是编译时常量。
    • 字符串的字节可以通过索引来获取,但是取元素的地址是非法的,即&s[i]是无效的。

反射

反射在计算机中是程序检查自己结构的一种能力,尤其是通过类型,它是元数据编程的一种方式,也是混乱的重要来源
每个语言的反射模型都不同(很多语言根本不支持它)

Type And interface

因为反射是建立在类型系统上,让我们先回顾一下Go中的类型。

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

type MyInt int

var i int
var j MyInt

变量i和j具有不同的静态类型,虽然他们具有相同的底层类型,但如果没有转换,则无法将他们分配给彼此。

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)
    ....

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

反射讲得比较好的一篇文章:https://juejin.im/post/5a75a4fb5188257a82110544

Go运行时

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

Interface

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

type IPerson interface{
}

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%扩容
  • nil切片的数组指针为nil,而空切片的数组指针指向一个没有分配任何内存空间的地址,即底层元素包含0个元素。不管nil切片还是空切片,对其调用append,len和cap的效果都是一样的。
  • 赋值:将一个切片赋值给另一个切片可指定索引
    • 第一个索引:指定切片的头部
    • 第二个索引:指定切片长度的尾部
    • 第三个索引:限制切片的容量

参考下面代码:

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字节,由于与切片关联的数据包含在底层数组里面,不属于切片本身,所以将切片复制给人以数组时对底层数组大小都不会有影响。

02e0d24ff450b8b144b44bcf7a68cd3b.png

映射

  • 键可以是任何值值,这个值的类型可以是内置的类型,也可以是结构类型,只要这个值可以使用 == 运算符做比较,切片、函数以及包含切片的结构类型由于具有引用意义,所以不能作为映射的键。
  • 映射的值可以为任何值
  • 赋值是通过指定适当的键并给这个键赋一个值来完成:colors["red"] = "#da1337"
  • 未初始化的映射称为nil映射,不能够进行赋值
  • 判断是否存在某个键
    • 同时获得值以及一个键是否存在的标记
    • 只返回键的值,通过判断键的值是否为零值判断是否存在

示例:

1、
value,exists := colors["blue"]
if exists{
    //  
}
2、
value := colors["blue"] 
if velue != ""{
    //
}
  • 通过键来索引映射时,即便这个键不存在的时候也总会返回一个值
  • 可通过for-range来迭代映射,for key,value := range colors{}
  • 可通过内置的delete函数将一个键值对从映射中删除,delete(colors,"orange")
  • 在函数中传递映射时,当这个映射被修改,所有对这个映射的引用都会察觉到这个修改,这个特性于切片类似,保证可以用很小的成本来复制映射。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值