Go语言核心36讲
郝林
《Go并发编程实战》作者,前轻松筹大数据负责人
立即订阅
24139 人已学习
课程目录
已完结 54 讲
0/4登录后,你可以任选4讲全文学习。
开篇词+学习路线 (3讲)
开篇词 | 跟着学,你也能成为Go语言高手
免费
预习篇 | 写给0基础入门的Go语言学习者
50 | 学习专栏的正确姿势
模块一:Go语言基础知识 (6讲)
01 | 工作区和GOPATH
02 | 命令源码文件
03 | 库源码文件
04 | 程序实体的那些事儿(上)
05 | 程序实体的那些事儿(中)
06 | 程序实体的那些事儿 (下)
模块二:Go语言进阶技术 (16讲)
07 | 数组和切片
08 | container包中的那些容器
09 | 字典的操作和约束
10 | 通道的基本操作
11 | 通道的高级玩法
12 | 使用函数的正确姿势
13 | 结构体及其方法的使用法门
14 | 接口类型的合理运用
15 | 关于指针的有限操作
16 | go语句及其执行规则(上)
17 | go语句及其执行规则(下)
18 | if语句、for语句和switch语句
19 | 错误处理(上)
20 | 错误处理 (下)
21 | panic函数、recover函数以及defer语句 (上)
22 | panic函数、recover函数以及defer语句(下)
模块三:Go语言实战与应用 (27讲)
23 | 测试的基本规则和流程 (上)
24 | 测试的基本规则和流程(下)
25 | 更多的测试手法
26 | sync.Mutex与sync.RWMutex
27 | 条件变量sync.Cond (上)
28 | 条件变量sync.Cond (下)
29 | 原子操作(上)
30 | 原子操作(下)
31 | sync.WaitGroup和sync.Once
32 | context.Context类型
33 | 临时对象池sync.Pool
34 | 并发安全字典sync.Map (上)
35 | 并发安全字典sync.Map (下)
36 | unicode与字符编码
37 | strings包与字符串操作
38 | bytes包与字节串操作(上)
39 | bytes包与字节串操作(下)
40 | io包中的接口和工具 (上)
41 | io包中的接口和工具 (下)
42 | bufio包中的数据类型 (上)
43 | bufio包中的数据类型(下)
44 | 使用os包中的API (上)
45 | 使用os包中的API (下)
46 | 访问网络服务
47 | 基于HTTP协议的网络服务
48 | 程序性能分析基础(上)
49 | 程序性能分析基础(下)
尾声与思考题答案 (2讲)
尾声 | 愿你披荆斩棘,所向无敌
新年彩蛋 | 完整版思考题答案
Go语言核心36讲
登录|注册

06 | 程序实体的那些事儿 (下)

郝林 2018-08-24
在上一篇文章,我们一直都在围绕着可重名变量,也就是不同代码块中的重名变量,进行了讨论。
还记得吗?最后我强调,如果可重名变量的类型不同,那么就需要引起我们的特别关注了,它们之间可能会存在“屏蔽”的现象。
必要时,我们需要严格地检查它们的类型,但是怎样检查呢?咱们现在就说。
我今天的问题是:怎样判断一个变量的类型?
我们依然以在上一篇文章中展示过的 demo11.go 为基础。
package main
import "fmt"
var container = []string{"zero", "one", "two"}
func main() {
container := map[int]string{0: "zero", 1: "one", 2: "two"}
fmt.Printf("The element is %q.\n", container[1])
}
那么,怎样在打印其中元素之前,正确判断变量container的类型?

典型回答

答案是使用“类型断言”表达式。具体怎么写呢?
value, ok := interface{}(container).([]string)
这里有一条赋值语句。在赋值符号的右边,是一个类型断言表达式。
它包括了用来把container变量的值转换为空接口值的interface{}(container)
以及一个用于判断前者的类型是否为切片类型 []string.([]string)
这个表达式的结果可以被赋给两个变量,在这里由valueok代表。变量ok是布尔(bool)类型的,它将代表类型判断的结果,truefalse
如果是true,那么被判断的值将会被自动转换为[]string类型的值,并赋给变量value,否则value将被赋予nil(即“空”)。
取消
完成
0/1000字
划线
笔记
复制
© 版权归极客邦科技所有,未经许可不得传播售卖。 页面已增加防盗追踪,如有侵权极客邦将依法追究其法律责任。
该试读文章来自付费专栏《Go语言核心36讲》,如需阅读全部文章,
请订阅文章所属专栏。
立即订阅
登录 后留言

精选留言(31)

  • 思想的宇屋 置顶
    真棒,这篇涉及到了自学go的gopher比较难涉及到的计算机基础和细节 如补码,类型转换异常时的“❓”
    2018-12-29
    4
  • 睡觉💤
    正数的补码等于原码,负数的补码才是反码+1
    2018-08-24
    74
  • 咖啡色的羊驼
    最开始写go时候也在string上遇到过一个小坑。

    由于是之前是phper,习惯性认为go中len("我")应该等于1,后面发现这个遇到字符串时候代表字节数。
    2018-08-24
    19
  • 陈悬高
    对于大型的代码库来说,能够重构其整体结构是非常重要的,包括修改某些 API 所属的包。大型重构应该支持一个过渡期:从旧位置和新位置获得的 API 都应该是可用的,而且可以混合使用这些 API 的引用。Go 已经为常量、函数或变量的重构提供了可行的机制,但是并不支持类型。类型别名提供了一种机制,它可以使得 oldpkg.OldType 和 newpkg.NewType 是相同的,并且引用旧名称的代码与引用新名称的代码可以互相操作。

    考虑将一个类型从一个包移动到另一个包中的情况,比如从 oldpkg.OldType 到 newpkg.NewType。可以在包 oldpkg 中指定一个新类型的别名 type OldType = newpkg.NewType,这样以前的代码都无需修改。
    2018-10-10
    18
  • 李皮皮皮皮皮
    1.通过类型断言获取变量实际类型value,ok=x.(T),ok表示是否是正确的类型,value是成功转换后的值,但返回值形式不建议使用,可能会导致panic
    2.go不同类型直接不能相互赋值,不存在隐式类型转换,必须显式强转
    3.type newType = oldType定义类型别名,type newType oldType定义新类型
    2018-08-24
    8
  • 我不会算法
    这节课,是从开始学习该专栏以来,最有价值的一节,没有之一!
    希望剩下的课程,都能像这节课这样有价值!

    作者回复: 尽量做到能让大多数人满意:)

    2018-10-11
    5
  • hello peter
    @咖啡色的羊驼 我也是phper,php中strlen('我')的结果应该是3,和go一样,你这习惯应该是js的吧
    2018-08-24
    4
  • @XP
    1.接口之间的类型转换有时只有运行错误,不会有编译错误
    2. 类型别名和原类型完全一样,可以随意命名,增加代码可读性; 拓展外部访问权限,原来的变宽
    不知道理解的对不对
    2018-08-24
    2
  • NoTryNoSuccess
    container := map[int]string{0: "zero", 1: "one", 2: "two"}
    value, _ := interface{}(container).(int)
    其实这样也不会报错呀,且value为0并不为nil,其中int也可以为其他任何与目标类型map不一致的类型。
    2019-06-27
    1
    1
  • 胖子(李杰)
    php 里面的strlen('你') 也不是1
    mb_strlen('你') 才是 1
    2019-05-16
    1
  • BitInit
    对于var str string = "hello 你好",使用len(str)结果是12,因为len(str)显示的string底层字节大小。如果需要str的大小,方法一是len([]rune(str)),将string转为rune切片,方法二是utf8.RuneCountInString(str)。对string进行range遍历时,是以unicode编码遍历的。
    2019-03-20
    1
  • 田佳伟
    首先你要知道,整数在 Go 语言以及计算机中都是以补码的形式存储的

    这句话应该是:首先你要知道,负数在 Go 语言以及计算机中都是以补码的形式存储的 吧😄

    作者回复: 正数的补码等于其自身。

    2018-09-06
    1
  • hb
    受益匪浅
    2018-08-29
    1
  • 小小笑儿
    好像golang已经支持名字不同但包含的字段相同的struct直接赋值?别名类型在代码重构中非常有用,例如以前使用的是p.T这个类型,重构过程中需要把它移到p1.T1,这时只需要在p包中定义type T=p1.T1,这样基本之前使用p.T的代码都不用修改。
    2018-08-24
    1
  • 我来也
    类型转换感觉跟c差不多。
    类型别名,我知道的三处优点:1.名字可以取的更通俗易懂;2:需要修改数据类型时,只用改定义的那一处地方;3:可以很方便的添加特有方法,以实现某些接口。
    2018-08-24
    1
  • 风一般的梦幻
    这一行:"其中的x可以是一个变量,也可以是一个代表值的字面量(比如1.23和struct{}),还可以是一个表达式。" 中的struct{}是否应改为struct{}{}?

    作者回复: 对的,我跟编辑说一下,谢谢。

    2019-10-28
  • Hector
    string可以被称为MyString2的潜在类型,那他们的区别到底在哪里呢?底层时做的复制动作,但是指针存放的地址不同吗

    作者回复: 我在文章里说了:“潜在类型相同的不同类型的值之间是可以进行类型转换的”。这属于语法规则。

    它们虽然代表着不同的类型,但本质上是同源的。也就是说,它们的底层结构是相同的。在这样情况下,在类型转换时值会被复制,即两个值会在不同的内存地址上。

    2019-05-10
  • Bitsman
    满满的干货
    2019-04-13
  • 赵梓旗
    您好,我有一个疑问,我认为文中提到的
    []MyString2 的潜在类型应该是它本身 []Mystring2
    同理,[]string 的潜在类型应该也是它本身 []string
    所以二者潜在类型不同,不能进行类型转换

    参考 https://go101.org/article/type-system-overview.html 中 「Concept: Underlying Types」小节的内容

    作者回复: 你可以参看一下,Go语言规范:https://golang.google.cn/ref/spec#Types ,这才是根本。

    2019-04-06
  • Leon Wong
    这一篇很精彩,思路清晰
    2019-03-20
收起评论
31
返回
顶部