浅谈Go类型转换之间的那些事
试着答一答这些问题
s[i]和(for _,v range)的v的区别是什么
var s string = "AB"
fmt.Println(reflect.TypeOf(s[0]))
for _, v := range s {
fmt.Println(reflect.TypeOf(v))
}
a.(),和 a(b) 的区别是什么?
var v interface{} = 1
var s uint8 = 1
temp1 := int(s)
temp2 := v.(int)
fmt.Println(temp1,temp2)
Go的类型系统了解
Go的类型
Go语言是一门静态编译型语言,是一门强类型语言,Go语言中类型分为两种:命名类型(已定义类型)和未命名类型(组合类型),我举例说一下
- 命名类型(已定义类型)
uint8(byte) uint16 uint32 uint64 int int8 int16 int32(rune) int64 bool string
float32 float64 complex64 complex128
上面举例类型归为三大类:,数值类型,字符串类型, 布尔值类型,我们使用type定义的任何类型也被称为命名类型,如下
//也是命名类型
type MyBool bool
- 未命名类型 (组合类型)
slice map chan function interface struct pointer
上面举例的类型有容器类型,函数类型,指针类型,结构体类型,通道类型,接口类型
自定义类型和底层类型
Go允许通过type关键字定义一个类型
Go的每一个类型都一个底层类型,类型的底层类型有如下规律
- 每一个命名类型的底层类型都是自己
- 每一个组合类型的底层类型都是自己
- 在一个类型的声明中,新声明的类型和原类型的底层类型是共享的
如下代码,请问这段代码能够编译成功吗?为什么?首先这段代码是编译失败的,i的类型是MyInt,j的类型是int,虽说她们的底层类型都是int,但不能相互赋值,也就说明命名类型间是不能相互赋值的,即便是低限制往高限制赋值,比如 int32 赋给 int64也是编译失败的
type MyInt int
func CustomType() {
var i MyInt = 2
var j int = 1
j = i
i = j
fmt.Println(i == j)
}
下面这段代码会打印这两个变量的基本类型和底层类型,
//输出MyInt int
fmt.Println(reflect.TypeOf(i), reflect.TypeOf(j))
//输出int int
fmt.Println(reflect.TypeOf(i).Kind(), reflect.TypeOf(j).Kind())
我们再来看一个Demo,下面这段代码编译会报错吗,如果把int32改成int64呢?答案是编译报错,改成int64也会编译报错,只有j和int32同时改成i和int64,才会编译成功。因为这时m和n的底层类型是完全相同的。
type MyM struct {
i int64
}
type MyN struct {
j int32
}
func TestStruct() {
n := MyN{j: 10}
var m MyM
m = MyM(n)
fmt.Println(n,m)
}
如何追踪朔源一个类型的的底层类型
如下代码,说说这些类型的底层类型是什么?
type MyInt int
type I MyInt
type Ints []int
type MyInts []MyInt
type M map[string]string
type CustomM M
MyInt的底层类型是int
I的底层类型时int
Ints的底层类型是[]int
MyInts的底层类型是slice
M的底层类是map
CustomM的底层类是map
规律就是直到找到的一个内置类型(Go内置的类型)或者未命名类型(组合类型)结束,这个类型就是当前类型的底层类型
怎么通过代码获取一个类型的底层类型呢?通过下面代码获取
reflect.TypeOf(variable).Kind()
类型别名
什么是类型别名呢?Go中有两个类型别名 byte,对应的真实类型是uint8,rune,对应的真实类型是int32,我们可以源代码中这两个的定义如下
// byte is an alias for uint8 and is equivalent to uint8 in all ways. It is
// used, by convention, to distinguish byte values from 8-bit unsigned
// integer values.
type byte = uint8
// rune is an alias for int32 and is equivalent to int32 in all ways. It is
// used, by convention, to distinguish character values from integer values.
type rune = int32
从这个就能就能解决最开始的第一个问题,s[index]取得是字符串转换成字节后的某一个字节,而range指的是循环字符串s的每一个字符(range会隐式的unicode解码), 但字符区分字母和汉字,一个字母占用一个字节,一个汉字可不是了,看如下代码,你可以获取byte和rune的底层类型
var r rune = 'c'
var b byte = 1
fmt.Println(reflect.TypeOf(r).Kind()) //int32
fmt.Println(reflect.TypeOf(b).Kind()) //uint8
如何定义一个类型别名呢?其实很简单,知道怎么定义一个类型,那么定义一个类型别名就很简单了,参考上面的byte和rune,如下我们为int64定义一个别名(从Go1.9开始支持),类型别名是可以被声明在函数体内的
//相比定义一个类型多了一个=号
type alaisInt64 = int64
类型转换和断言
类型转换是用来在类型不同但相互兼容的类型之间的相互转换的方式,如果不兼容,则无法相互转换,编译会报错,通常写法是 a(b),把b转换成a
类型断言是在接口之间进行,本质也是类型转换,写法是a.(b),含义是把a转换成b
如下代码,做一些错误的和正确的示范
//这个转换时类型不同,也不兼容,所以编译报错
s := "ab"
i := int(s)
//这个转换类型不同,但兼容,所以OK
var j int8 = 1
m := int(j)
//这个转换是失败的,系统会检测到类型不匹配,直接panic
var k interface{} = "s"
l := k.(int)
//但我们可以通过一个参数来判断,只有f为true时,才会转换成功
l,f := k.(int)
//这个转换是成功的
p,f := k.(string)
类型转换的实践,勤加练习才能理解
数字类型之间转换
从低位转高位没有什么问题,从高位转低位时(会丢失精度),int64转int8,这个转换的过程如下:
128的二进制:.........00000000_10000000
因为是从int64转int8,所以截取128的后八位 :10000000
此时最高位是1,表示这是一个负数,此时结果是就是:-128
//这个转换没有任何问题,都OK
var i int8 = 123
var j int16 = int16(i)
//这个转换会丢失精度,从高位转低位
var m int64 = 128
var n int8 = int8(m) //n的结果是-128,因为int8能表达的最大值是127,最小值是-128,
字符串,字节,数字,字符互相转换
var s1,s2 string = "AbcD","1234"
//转字节
bs1 := []byte(s1); bs2 := []byte(s2)
//字节数组转字符串
s11 := string(bs1); s22 := string(bs2)
//单个字节转字符串
ss := string(bs1[0])
fmt.Println(s11, s22, ss)
//s2转数字 ,err 表示是否能转换成功,比如s1就会转换失败
i, err := strconv.Atoi(s2)
//数字转字符串
s := strconv.Itoa(i)
//字符串转字符数组
runes := []rune(s1)
//字符数组转字符串
ss1 := string(runes)
//单个字符转字符串
ss2 := strconv.QuoteRune(runes[0])
//字符转字节
bss := make([]byte, 0)
bss = strconv.AppendQuoteRune(bss, runes[0])
fmt.Println(err, s, ss1, ss2, runes[0], bss, string(bss))
//除开rune和byte底层的类型的区别,在使用上,
//rune能处理一切的字符,而byte仅仅局限在ascii
//整形转字节
x := int32(68)
bytesBuffer := bytes.NewBuffer([]byte{})
binary.Write(bytesBuffer, binary.BigEndian, x)
//字节转整形
var y int32
binary.Read(bytesBuffer, binary.BigEndian, &y)
接口到具体类型的转换
//由接口类型转换为具体的类型
var i interface{} = 1
t, f := i.(int)
if f { //转换成功
fmt.Println(t)
} else {//转换失败
fmt.Println(reflect.TypeOf(i).Kind(), reflect.TypeOf(i))
}
欢迎关注公众号,阅读更多精彩文章

浅谈Go类型转换之间的那些事的更多相关文章
- 就该这样理解 OSI 七层参考模型、浅谈不同局域网之间的通信
简介 说到OSI参考模型,理解网络与网络之间的关系,不说太深入难以理解的东西,只求能最大程度上理解与使用. 参考模型是国际标准化组织(ISO)制定的一个用于计算机或通信系统间互联的标准体系,一般称为O ...
- 浅谈Oracle表之间各种连接
Oracle表之间的连接分为三种: 1.内连接(自然连接) 2.外连接 2.1.左外连接(左边的表不加限制,查询出全部满足条件的结果) 2.2.右外连接(右边的表不加限制,查询出全部满足条件的结果) ...
- 浅谈UML中类之间的五种关系及其在代码中的表现形式
本文转载:http://www.cnblogs.com/DebugLZQ/archive/2013/05/13/3066715.html 什么是类? 将某类东西归纳在一起,可以成为一个类. 类有很多种 ...
- java中的装饰设计模式,浅谈与继承之间的区别
最初接触装饰设计模式,一直搞不懂这么做的意义是什么,看了网上很多的资料,对于与继承的区别并没有很清楚的分析,直到看到这篇博客:http://www.cnblogs.com/rookieFly-tdii ...
- 浅谈MVC页面之间参数传递
关于MVC页面之间的传值,有多种方式,下面,我们就Html.RenderAction 方式 和 Html.RenderPartial 方式 来给大家分享一下有什么不同. 一.Html.RenderAc ...
- 《Machine Learning in Action》—— 浅谈线性回归的那些事
<Machine Learning in Action>-- 浅谈线性回归的那些事 手撕机器学习算法系列文章已经肝了不少,自我感觉质量都挺不错的.目前已经更新了支持向量机SVM.决策树.K ...
- 【ASP.NET MVC系列】浅谈ASP.NET 页面之间传值的几种方式
ASP.NET MVC系列文章 [01]浅谈Google Chrome浏览器(理论篇) [02]浅谈Google Chrome浏览器(操作篇)(上) [03]浅谈Google Chrome浏览器(操作 ...
- 浅谈 kubernetes service 那些事(上篇)
一.问题 首先,我们思考这样一个问题: 访问k8s集群中的pod, 客户端需要知道pod地址,需要感知pod的状态.那如何获取各个pod的地址?若某一node上的pod故障,客户端如何感知? 二.k8 ...
- 浅谈 kubernetes service 那些事 (下篇)
欢迎访问网易云社区,了解更多网易技术产品运营经验. 五.K8s 1.8 新特性--ipvs ipvs与iptables的性能差异 随着服务的数量增长,IPTables 规则则会成倍增长,这样带来的问题 ...
随机推荐
- 从 SGD 到 Adam —— 深度学习优化算法概览(一) 重点
https://zhuanlan.zhihu.com/p/32626442 骆梁宸 paper插画师:poster设计师:oral slides制作人 445 人赞同了该文章 楔子 前些日在写计算数学 ...
- JavaScript setTimeout this对象指向问题
上面这幅图片是原始的效果, 现在想鼠标移到图标上,显示图标的提示,但需要延时,也就是鼠标滑至图标上,并不立刻显示,而是等1秒后显示. html部分 <div class="porHea ...
- poj 3624 Charm Bracelet(01背包)
Charm Bracelet Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 29295 Accepted: 13143 ...
- Spring Security实现禁止用户重复登陆(配置及原理)
系统使用了Spring Security做权限管理,现在对于系统的用户,需要改动配置,实现无法多地登陆. 一.SpringMVC项目,配置如下: 首先在修改Security相关的XML,我这里是s ...
- Vue的Router路由传参
一.文件结构 二.vue.js 打开此链接 https://cdn.bootcss.com/vue/2.6.10/vue.js 复制粘贴页面的所有内容 三.vue-router.js 打开此链接 h ...
- turtle 20秒画完小猪佩奇“社会人”
转载:https://blog.csdn.net/csdnsevenn/article/details/80650456 图片源自网络 作者 丁彦军 如需转载,请联系原作者授权. 今年社交平台上最火的 ...
- 【9101】求n!的值
Time Limit: 10 second Memory Limit: 2 MB 问题描述 用高精度的方法,求n!的精确值(n的值以一般整数输入). Input 文件输入仅一行,输入n. Output ...
- UVa1601 - The Morning after Halloween [单向bfs]
解题思路: 1.注意到2*2方格中必有一个#,那么最多只有192条通道,可以将所有非‘#’的位置提取出来用邻接表的方式建图,通过bfs搜索目标位置. 2.将三个ghost的位置(a,b,c)作为状态量 ...
- CF241B Friends
CF241B Friends 和Tree and Xor思路一样CF1055F Tree and XOR 直接找到第k大val,可以直接建出trie,然后按位贪心 考虑比val大的数的和 还是用b[i ...
- H3C 端口隔离简介