虚位以待(AD)
虚位以待(AD)
首页 > 软件编程 > GO语言 > golang新手不注意可能会出现的一些小问题

golang新手不注意可能会出现的一些小问题
类别:GO语言   作者:码皇   来源:互联网   点击:

最近在学习golang,发现了一些新手们需要注意的小问题,下面这篇文章主要给大家介绍了关于golang新手不注意可能会出现的一些小问题,文中通过示例代码介绍的非常详细,需要的朋友可以参考借鉴,下面来一起看看吧。

go简介

语言哲学

C语言是纯过程式的,这和它产生的历史背景有关。Java语言则是激进的面向对象主义推崇者,典型表现是它不能容忍体系里存在孤立的函数。而Go语言没有去否认任何一方,而是用批判吸收的眼光,将所有编程思想做了一次梳理,融合众家之长,但时刻警惕特性复杂化,极力维持语言特性的简洁,力求小而精

Go语言反对函数和操作符重载(overload),而C++、Java和C#都允许出现同名函数或操作符,只要它们的参数列表不同。

其次,Go语言支持类、类成员方法、类的组合,但反对继承,反对虚函数(virtual function)和虚函数重载。确切地说,Go也提供了继承,只不过是采用了组合的文法来提供

最近在整理之前写程序,学习时所记录的有道云笔记,发现一些有意思的小点跟大家分享一下。如有错误请大家给指出

一、闭包 defer

闭包(匿名函数)

    func test(){
    i, n := 1 ,2;
    defer func(a int){
    fmt.Println("defer:", a , n);
    //n被闭包引用 }
    (i) //复制i的值 i , n = i+1,n+2;
    fmt.Println(i , n);
    }

我们看一下结果:

    2 4defer: 1 4

为什么会这样?是因为闭包复制的是原对象指针,出现了延迟引用现象。我们在使用闭包的时候要注意这个问题,同样在for 循环中 也会出现类似现象。

二、Map

前一段时间在论坛看到一个问题

    type Data struct{
    AABB [2]float64}
    var m map[string]Data = make(map[string]Data,1)m["xxx"] = Data{
    }
    m["xxx"].AABB[0]=1.0m["xxx"].AABB[1]=2.0<br data-filtered="filtered">#以上代码go build 通不过,错误提示cannot assign to m["xxx"].AABB[0]

这是一个网友给出的答案

    type Data struct{
    AABB [2]float64}
    m := make(map[string]*Data,1)m["xxxx"] = Data{
    }
    m["xxxx"].AABB[0] = 1.0m["xxxx"].AABB[1] = 2.0#这样写就对了,你的 m["xxxx"] 返回的是值,不是一个可取地址的变量

这个网友的答案可以编译成功,但是不可取,他犯了很多新手都容易出现的问题

why?Golang中的map元素属性被设计为只读的,并不期望被修改,并且从 map 中取回的是一个value也是临时复制品。并且map是一个hash 结构,当hash扩容时,键值的存储位置就会发生改变。如果这个时候我们对 m["xxxx"].AABB[0] = 1.0 修改,不知道指针会发什么。大家有兴趣可以看看Go Hashmap内存布局和实现

如果我们想修改最好这样

    type Data struct{
    AABB [2]float64}
    m := make(map[string]*Data,1)m["xxxx"] = &Data{
    }
    d := m["xxxx"]d.AABB[0] = 1.0d.AABB[1] = 2.0m["xxxx"] = d

三、nil

先看一段代码,当然这种场景不常见,但是能让我们更好的理解nil

    func t(){
    var i *int = nil;
    var n interface{
    }
    = i;
    fmt.Println(n==nil);
    //false}

可能很多小伙伴都会有疑问都是nil 为啥会不相等。我们先分别看一下pointer,interface的结构体和当pointer,interface为nil时的结构

    uintptrtype interfaceStruct struct {
      v *_value // 实际值  t *_type // 实际值的类型信息}
    uintptr(0) == niltype interfaceStruct struct {
      v:uintptr(0)  t:uintptr(0)}
    == nil

由此我们可以看出nil其实就是指针 interface的零值

这时候我们在来解释为啥为flase就很容易了

    func t(){
    var i *int = nil;
    // (*int)nil var n interface{
    }
    = i;
    // interace{
    }
    ((*int)nil) fmt.Println(n==nil);
    // type interfaceStruct struct {
                     // v: uintptr(0),                 // t: (*int)                 // }
    }

官方文档规定可以为nil的类型还有 slice ,map ,channel ,function 。

可能有些朋友可能会问为啥没有error类型,那是因为error 只是程序预设的接口方法, err nil 也会出现类似的问题,官方有一个文档也给出了解释,传送门

    type error interface {
    Error() string }
      

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对脚本之家的支持。

您可能感兴趣的文章:

  • Go语言中的Slice学习总结
  • GO 语言学习指南
  • Go语言学习笔记之反射用法详解
  • Go语言基础学习教程
  • Go语言函数学习教程
  • Go语言学习教程之声明语法(译)
相关热词搜索: golang golang defer golang map 实现