V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
The Go Programming Language
http://golang.org/
Go Playground
Go Projects
Revel Web Framework
ztao8607
V2EX  ›  Go 编程语言

准备冲锋 golang 入坑系列

  •  
  •   ztao8607 · 2017-11-21 10:01:23 +08:00 · 2509 次点击
    这是一个创建于 2560 天前的主题,其中的信息可能已经有所发展或是发生改变。

    读前必读: 第一次在 V2EX 发帖才知道发完贴就不能再编辑了。所以上篇文章中有一些单词拼写错误,无法及时修改。 好在原文已经修改,所以感谢上苍还能给我一个修正错误的地方。(但还是要吐个槽,V2EX 的 markdown 为啥不支持我写的表格,是我姿势不对么?) 最新的文章发布在gitbook,若您感觉写的还凑合,也希望能给个 star。若您感觉我写的罗里吧嗦,恩,可提可不提,随您意吧。平时和人贫惯了,写点东西也带上了这股贫劲。所以一时半会很难改,因此您提归提,我够呛能改掉.....

    好,一行小字交代完,下面开始 show time.

    树活一张皮,人活一张脸。文章好不好,标题最重要。光起名就想了 10 几分钟,中国汉语博大精深,但适合做技术类标题的真心太难想了。标题不够,写诗来凑,所以来段绕口小段子算是开场:

    守法朝朝忧闷,强盗夜夜欢歌。 损人利己骑马骡,正直公平却挨饿。 修桥补路瞎眼人,杀人放火事儿真多。我到西天问我佛,佛说:我 TM 也没辙。

    看完,乐完。收拾心情,开始继续学 Golang。

    在上一节,你学会了写第一个 Golang 程序,也知道了 Golang 的程序结构。我不知道你是什么技术背景,也不知道有多少编码功底。所以有的地方写的比较啰嗦,懂了,就一笑而过。不懂,就好好看一下。知识多了,不丢人。不懂装懂,最可怕。

    这一节,你将接触到 Golang 的基本数据类型。

    自打有编程语言开始,基本类型就三类:布尔,字符 /字符串,数值(和其它)。不同的语言,对类型有不同的分类标准,就会衍生出更为细致的分类,但本质就这么三类。其它语言,咱先不管。先来看看 Golang 的类型划分:

    • 布尔类型

    只有两个值,true 或者 false。记住只有这两个值。别的语言可以通过 0 或者 1 来充当布尔判断,但在 golang 里面不行(笔杆子出真理,不行就自己写个代码来验证一下)。golang 只认 true or false。

    • 字符 /字符串

    字符多了就是字符串。 从内存上来说,字符串就是内存中连续排列的字符的集合。在内存当中保存的都是 01 这样的二进制,不会保留一个汉字或者字母。所以每个字符都对应着一个数字,这个数字就是 ASCII 码里面的值。比如十进制的 33 就是'!'。虽然字符对应的是数字,但 Golang 仍然赋予字符一个特定的类型叫做 byte。你可以这么定义一个字符:

    var c byte
    c = 33
    

    字符多了就是串,所以字符串类型 string 也可以理解成是[]byte(byte 数组)。提醒一点,Golang 的字符串是不可更改的。 记住即可,日常中不会体会到,除非装 X 较真的时候(比如面试)会提到。这里的不可更改指的是下面的场景:

    str := "Who said string cannot change?"
    str = "I don't konw"
    

    str 仍然是哪个 str,但 str 指向的内存地址已经变了。str 只是一个名字,一个代号而已,拿掉这个代号,str 又是什么东西(写这段的时候,刚好旁边在放武林外传吕秀才口擒姬无命那段,所以直接用了,应该没有版权问题)? 上面说到字符串是内存中连续的字符集合,所以当你对字符串修改时,其实是将一段新的内存给了 str。因此才会说字符串是不可更改的。因为从来都是给它赋新值,旧值直接被垃圾回收了。 这段记住即可,除了面试,其它没有会被提到的场合。

    • 数值类型

    这个类型需要好好说一下了,因为衍生的类型太多了。但多归多,真正使用的就那么几个(谁用谁知道)。 (不支持我的表格语法,如果感觉格式凌乱,建议去 gitbook 看)

    | 整型值 | | --- |

    | 序号 | 类型和取值范围 | | --- | --- | | 1 | uint8 无符号 8 位整型 (0 to 255) | | 2 | uint16 无符号 16 位整型 (0 to 65535) | | 3 | uint32 无符号 32 位整型 (0 to 4294967295) | | 4 | uint64 无符号 64 位整型 (0 to 18446744073709551615) | | 5 | int8 有符号 8 位整型 (-128 to 127) | | 6 | int16 有符号 16 位整型 (-32768 to 32767) | | 7 | int32 有符号 32 位整型 (-2147483648 to 2147483647) | | 8 | int64 有符号 64 位整型 (-9223372036854775808 to 9223372036854775807) |

    一句话点明:无符号整型只能表示正数,有符号的可以表示负数。但数的个数是相同的(自己找个笔头,算算二进制就知道了)

    (不支持我的表格语法,如果感觉格式凌乱,建议去 gitbook 看)

    | 浮点数 | | :---: |

    | 符号 | 类型和取值范围 | | :--- | :--- | | 1 | **float32 **32 位浮点数 | | 2 | **float64 **64 位浮点数 | | 3 | **complex64 **实部虚部都是一个 float32 的复数 | | 4 | **complex128 **实部虚部都是一个 float64 的复数 |

    Golang 里面没有 float 类型,所以需要浮点数的时候需要指明长度。 除了计算和钱有关的程序(计算利息,收益等等),基本上很少会用到浮点数。 (不支持我的表格语法,如果感觉格式凌乱,建议去 gitbook 看)

    | 其它数值类型 | | :---: |

    | 序号 | 类型 | | :--- | :--- | | 1 | byte等同于 uint8 | | 2 | rune等同于 int32 | | 3 | **uint **等同于 32 or 64 bits | | 4 | **int **等同于 uint | | 5 | uintpt 指针类型 CGO 里面经常用到 |

    上面列出了 Golang 当中所有的数值类型,大部分而且是绝大部分是不常用到的。经常用的就是 int, byte 再加上 float32/64,没有其它。

    甚至有的时候,你都不知道用的是什么类型,例如:

    i := 0
    

    很可能你就直接声明了一个变量。这个变量什么类型, who care? 不能说你错,因为我也经常这么干。但我知道 i 是 int 型🙄。 刚开始写 golang,别被老司机带坏了。老老实实的声明变量类型,等你变老了,再去调戏小姑娘

    var i int
    i = 0
    

    没有人会问到常量么? 在有的文章或者教程中,常量也被归纳到类型中.Golang 官方里面没有这么提,所以尊重原创,我也不认为常量算是一种类型。

    变量

    类型是为变量服务的,类型是衣,变量是皮。前面你所写的 golang 代码中已经有变量了,但却只其有而不知它为啥有,看下面就让你知道变量是怎么回事。

    说的官方点,变量只不过是给程序可以操作的存储区域的名称而已。Go 中的每个变量都有一个特定类型,该类型决定变量内存的大小和布局,可以存储在该内存中的值的范围,以及可以应用于该变量的操作集。

    这种话,说出来都绕口。 通俗大白话,变量就是一种保存在内存里的数据结构。

    变量名只能有字母,数字或者下划线来组成。但必须以字母或者下划线开头,别找事,用数字开头。那就是自己挖坑自己遭殃。自己作孽自己 die。因为 Golang 对大小写敏感,所以首字母是否要大写,根据是否可见来判断。 如果不保准,就小写。等着后悔了,改成大写也来得及。

    Golang 也允许定义各种其他类型的变量,例如枚举、指针、数组、结构和 Union,为了体现本书内容的厚度,我们放在以后的章节中讨论这些变量。在本章中,将只关注基本的变量类型。

    声明变量的基本格式是:

    var 变量名称 变量类型
    

    也可以采用:

    变量名称 := 初始值
    

    但还是那句话,没练成老司机,就别调戏小姑娘。老老实实的用第一种吧。如果某天看到下面的声明方式也别奇怪:

    var  i, j, k int
    

    golang 支持同时声明多个变量。 上面就声明了三个 i、j 和 k 三个 int 类型的变量。一般来说,声明完之后,就择机进行初始化。

    i = 4
    j,k = 5,6
    

    可以单独给某个变量赋值,也可以同时给多个变量赋值。 喜欢哪个就用哪个,高兴就好。

    像这种通过 var 来声明的变量,称之为静态变量。 也就是编译器在编译阶段就可以知道数据类型的变量。 反之就是动态变量,也就是通过 i := 0 这种,运行时才能推导出变量类型。 不用担心,两者在效率上是否有区别。 现在的 CPU 老牛 X 了,不在乎这点差距。

    介绍完常规命名方式,下面来介绍个"孔乙己"式的方式:

    var a, b, c = 3, 4, "foo"
    

    花哨不实用,知道即可。非要练,请自便~ 小心被团队里的其它人打折腿。

    Golang 的变量还是很简单的,实用的就那么几招,学会了就真的学会了,没有花架子。

    本节起名是准备冲锋。冲锋之前,送你一把称心称手的兵器。介绍一个 IDE

    Goland

    IDE 大厂 JetBrains 推出的专业 Golang IDE。 现在还是预览版,所以不要钱。 趁着免费赶紧用吧。当哪天收费了,撸起袖子去找破解 Key 吧。

    安装好 Goland 之后,基本上什么都不需要配置,开箱既用。唯独需要你自己维护一下 GOPATH。 不知道何为 GOPATH ? 老铁,上点心,别吃完饭就忘... 翻到前面几节复习一下。

    Goland 的 GOPATH 设置在 Preferences --> Go --> GOPATH. 里面有全局 GOPATH 也有项目 GOPATH,根据自己的需要,自己维护一下。如果心情好,可以顺手去维护了 GOROOT。反正是 no zuo no die。 工程跑不起来,还是自己受伤💔。

    所以只维护 GOPATH 就好。

    第一式,亢龙有悔就结束了。 入门没入门? 没入门... 再从第一节读一遍,保证入门。 入了门? 看看有没有点 star,没点赶紧点一个。每节最后我都提示一下,反正是为了凑字数..

    15 条回复    2017-11-23 14:29:58 +08:00
    Daizong
        1
    Daizong  
       2017-11-21 10:06:40 +08:00
    支持一个,希望二三线城市也流行起来。
    OMGZui
        2
    OMGZui  
       2017-11-21 10:14:34 +08:00
    支持下作者
    hsuan
        3
    hsuan  
       2017-11-21 10:16:18 +08:00 via Android
    之前的哪里有?
    ztao8607
        4
    ztao8607  
    OP
       2017-11-21 10:58:48 +08:00
    @hsuan 最新的文章都在 gitbook 上面。https://andy-zhangtao.gitbooks.io/golang/content
    Marmot
        5
    Marmot  
       2017-11-21 11:02:28 +08:00
    可以的,支持一波,想当初都是自己摸索的。
    GooMS
        6
    GooMS  
       2017-11-21 12:02:03 +08:00 via Android
    Gopath go root 傻傻分不清楚
    ztao8607
        7
    ztao8607  
    OP
       2017-11-21 12:06:27 +08:00
    topthink
        8
    topthink  
       2017-11-21 12:09:04 +08:00
    点赞 可以放到看云上,国内阅读速度快一些
    GooMS
        9
    GooMS  
       2017-11-21 12:14:04 +08:00 via Android
    @ztao8607 gopath 是一个固定的依赖目录?还是每个项目都需要一个,主要我看还需要设置环境变量。
    JohnDeng
        10
    JohnDeng  
       2017-11-21 13:39:15 +08:00
    > 当哪天收费了,撸起袖子去找破解 Key 吧。

    加了这句就不是很好了啊,不怕给查水表了。
    ysicing
        11
    ysicing  
       2017-11-21 14:04:27 +08:00
    支持一下涛哥 = =
    ztao8607
        12
    ztao8607  
    OP
       2017-11-21 14:12:59 +08:00   ❤️ 1
    @GooMS GOPATH 是环境变量。 很多 IDE 都将其做成了设置项。GOPATH 放的都是 go 源码, 编译的时候,通过$GOPATH/src 这样的规则去查找所需要的 package,然后 build。 所以 GOPATH 里面可以设置多个 path,也可以根据项目,一个项目设置一个 GOPATH。具体采用哪种方式,依据当前团队的代码管理来确定
    ztao8607
        13
    ztao8607  
    OP
       2017-11-21 14:13:39 +08:00
    @ysicing 呵呵,他乡遇故音,可遇不可求呀。:D
    lepig
        14
    lepig  
       2017-11-23 10:33:31 +08:00   ❤️ 1
    看了[gitbook]( https://andy-zhangtao.gitbooks.io/golang/content/chapter1/zhun-bei-chong-feng.html)这篇“其他数值类型”的表格中第 4 行写到 `int 等同于 uint`

    ```go
    func main() {
    var i int = 9223372036854775808
    fmt.Println(i) //./main.go:16: constant 9223372036854775808 overflows int
    }
    ```
    那如果是无符号的 uint 岂不是 0-18446744073709551615 范围都可以吗?
    我是 win7 64 我在 linux 64 上也是这个问题
    ztao8607
        15
    ztao8607  
    OP
       2017-11-23 14:29:58 +08:00
    @lepig 我也遇到了这个问题。当时为了保证数据正确性,所有数据都取自 Golang 官方文档,没有做实际验证。 是在对不起! 因为 V2 没法再修改原文了,所以我再原文中标注了,实际结果和官方数据的差异。 因为 Golang 在 1.9.1 之前有一些类型取值的 bug,不知道这个算不算。 等 golang 有了官方说明,我会再次修改原文。
    再次感谢,指出文中的错误! 谢谢!
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2805 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 25ms · UTC 07:55 · PVG 15:55 · LAX 23:55 · JFK 02:55
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.