golang的一些特性

一,slice特性

func main() {

    var a map[string][]string = make(map[string][]string)

    a["11"] = []string{"aa", "bb"}

    var b map[string][]string = make(map[string][]string)

    for k, info := range a {

        b[k] = append(b[k], info...)  //append 申请了一份内存并进行值拷贝

    }

    var c map[string][]string = make(map[string][]string)

    for k, info := range a {

        c[k] = info  //c["11"]引用a["11"]的slice内存对象而已

    }

    a["11"][0] = "xx"

    for k, v := range a {

        fmt.Println(k, v)

    }

    for k, v := range b {

        fmt.Println(k, v)

    }

    for k, v := range c {

        fmt.Println(k, v)

    }

}

打印:

11 [xx bb]
11 [aa bb]
11 [xx bb]

二,map特性

1,map赋值仅是赋值指针变量的赋值

var  g_map  map[key]value 

并发访问map的技巧,定时更新map(定时指针赋值):在更新线程中,需要创建一个全新的map(注意这个map是在更新线程的函数栈中,对其它线程不可见),在更新线程中赋值完这个新map后,再使用该新map赋值给全局map:g_map = New_map;在赋值过程中(最多仅有三个指令),读线程要么读到老的g_map,要么读到新的new_map,因此不会有map并发的读写问题。

2,map赋值指针后,原正在被消费的指针所指的对象依然可用(不会崩溃)

var whiteDomainMp = make(map[string]map[string]bool)

func readMap() {
    for {
        for k, v := range whiteDomainMp {
            time.Sleep(time.Second)
            fmt.Printf("k:%s v:%+v\n", k, v)
            for k1, v1 := range v {
                fmt.Printf("k:%s v:%+v\n", k1, v1)
            }
        }
    }
}

func main() {
    whiteDomainMp["a"] = make(map[string]bool)
    whiteDomainMp["a"]["aa"] = true

    whiteDomainMp["b"] = make(map[string]bool)
    whiteDomainMp["b"]["bb"] = true

    whiteDomainMp["c"] = make(map[string]bool)
    whiteDomainMp["c"]["cc"] = true

    whiteDomainMp["d"] = make(map[string]bool)
    whiteDomainMp["d"]["dd"] = true

    go readMap()
    for {
        var tmp = make(map[string]map[string]bool)
        tmp["a1"] = make(map[string]bool)
        tmp["a1"]["aa1"] = true

        tmp["b1"] = make(map[string]bool)
        tmp["b1"]["bb1"] = true

        tmp["c1"] = make(map[string]bool)
        tmp["c1"]["cc1"] = true

        tmp["d1"] = make(map[string]bool)
        tmp["d1"]["dd1"] = true
        time.Sleep(time.Duration(2) * time.Second)
        whiteDomainMp = tmp
        fmt.Printf("whiteDomainMp = tmp\n")
    }
}

3,map不支持并发的读写,例如 var  v  map[key]value,不能并发的读写遍历key;即使key固定(不再新增或删除),也不能并发的读写value;测试代码:会导致map并发读写崩溃!

func readRoutine() {
    for {
        for k, p := range gMp {
            fmt.Println(k, *p)
        }
    }
}

func writeRoutine() {
    for {
        for k, p := range gMp {
            fmt.Println(*p)
            new := fmt.Sprintf("%d", time.Now().Unix())
            gMp[k] = &new
        }
    }
}

var gMp map[string]*string = make(map[string]*string)

func main() {
    var a = "aaa"
    gMp["a"] = &a

    var b = "bbb"
    gMp["b"] = &b

    var c = "ccc"
    gMp["c"] = &c

    go readRoutine()
    go writeRoutine()
    go readRoutine()
    go writeRoutine()

    for {

    }
}

三,接口的特性

        接口类型可以关联不同类型的对象,以统一的方式调用不同对象的执行方法。例如下例 a、o 对象可以转成 lPrice 接口对象 i,调用 i.CalPrice() 会执行相应 a,o 对象类型的 CalPrice 方法。

type IPrice interface {
    CalPrice(cnt int) int
}

type Apple struct {
    Price int
    Color string
}
type Orange struct {
    Price  int
    weight int
}

func (a Apple) CalPrice(cnt int) int {
    return cnt * a.Price
}
func (o Orange) CalPrice(cnt int) int {
    return 3 + cnt * o.Price
}

func main() {
    a := Apple{Price: 7}
    o := Orange{Price: 4}
    var iobj []IPrice
    iobj = append(iobj, a, o)
    for _, i := range iobj {
        fmt.Println(i.CalPrice(3))
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值