golang进阶之路

栏目: Go · 发布时间: 7年前

内容简介:go语言提供了一种在不同但是相互兼容的类型之间相互转换的方式,并且这种转换非常安全。非数值类型之间的转换不会丢失精读。 但是对于数值类型之间的转换,可能会发生丢失精度或其他问题。由于x超出了int16的范围,所以y的值会被设置成-535。对于数字,本质上将我们可以将任意的整型或者浮点型数据转换成别的整型或浮点型(要考虑丢失精度问题)。

类型转换

go语言提供了一种在不同但是相互兼容的类型之间相互转换的方式,并且这种转换非常安全。非数值类型之间的转换不会丢失精读。 但是对于数值类型之间的转换,可能会发生丢失精度或其他问题。

转换语法

resultOfType := Type(exportession)

例如

x := uint16(6500)
y := int16(x)

由于x超出了int16的范围,所以y的值会被设置成-535。

对于数字,本质上将我们可以将任意的整型或者浮点型数据转换成别的整型或浮点型(要考虑丢失精度问题)。

string类型转换

一个字符串可以转换成一个[]byte(其底层位UTF-8的字节)或者一个[]rune(Unicode码点),并且[]byte和[]reune都可以转换成一个字符串类型。单个字符是一个rune类型数据(即int32), 可以转换成一个单字符的字符串。

类型转换的高级用法

Go语言的interface{}类型用于表示空接口,同时也可以用来表示任意 Go 类型的值。 此外,我们可以使用 类型断言类型开关 或者GO语言的 reflect包 的类型检查将一个interface{}类型的值转换成一个实际数据的值。

1、类型断言

语法

resultOfType, boolean := expression.(Type)  //安全类型断言 这里的Type是一个具体的Go类型,如int
resultOfType := expression.(Type)  //非安全类型断言,失败是panic

成功的安全类型断言将返回目标类型的值和表示成功的true。如果安全类型断言失败(即表达式的类型与声明的类型不兼容),将返回目标类型的零值和false。

非安全类型断言要么返回一个目标类型的值,要么panic抛出异常。

示例

var i interface{} = 99
var s interface{} = []string{"left", "right"}
j := i.(int) //j是int类型的数据(或者panic)
fmt.Printf("%T -> %d \n", j, j)

if i, ok := i.(int); ok{
fmt.Prinf("%T -> %d \n", i, j)   //i 是一个int类型的影子变量
}
if s, ok := s.([]string); ok{
fmt.Prinf("%T -> %q \n", s, s)  //s 是一个[]string类型的影子变量
}

输出

int -> 99
int -> 99
[]string -> ["left" "right"]

做类型断言时将结果复制给与原始变量同名的变量是很常见的事情,即使用影子变量。

上面示例中,如果我们输出原始的i和s变量(两者都是interface{}类型),它们可以以int和[]string类型的形式输出。因为fmt包的打印函数遇到interface{}类型时,会智能的打印实际类型的值。

2、类型开关

当我们使用interfa{}类型的变量时,我们常常需要访问其底层值。如果知道其底层值类型,就可以使用类型断言,但是如果其类型可能是很多类型的一种,就可以使用类型开关。

语法

switch optional; typeSwitch{
case typeList:
...
case typeList:
default:

示例

package main

import "fmt"

func main() {
    classfier(10, "string", 1.2)
}

func classfier(items ...interface{}) {
    for i, x := range items {
        switch x.(type) {
        case bool:
            fmt.Printf("param #%d is a bool\n", i)
        case float64:
            fmt.Printf("param #%d is a float64\n", i)
        case int, int8, int16, int32, int64:
            fmt.Printf("param #%d is a int\n", i)
        case string:
            fmt.Printf("param #%d is a string\n", i)
        case nil:
            fmt.Printf("param #%d is a nil\n", i)
        default:
            fmt.Printf("param #%d is a unknow\n", i)

        }
    }
}

输出

param #0 is a int
param #1 is a string
param #2 is a float64

这里使用的类型开关守护与类型断言里的格式一样,即 var.(Type),但是这里的type是一个关键字而非实际类型,用于表示任意类型。

类型开关的升级用法:

当我们解析JSON格式的数据,我们必须将数据转换成相对应的Go语言数据类型。这也可以通过GO标准库的json.Unmarshal()函数来实现。 我们想该函数传入一个只想结构体的指针,该结构体又与该json数据字段相匹配,那么该函数就会将JSON数据中对应的数据项填充到结构体的每一个字段。 但是如果我们事先不知道JSON数据的结构,那么就不能给json.Unmarshal()函数传入一个结构体。这种情况下,我们可以给该函数传入一个指向interfa{}的指针,这样json.Unmarshal()函数就会将其设置成引用一个map[string]interface{}类型值,其键位json字段的名字,值位对应的保存为interfa{}的值。

示例

func JsonUnkow() {
    MA := []byte(`{"name": "Massachusetts", "area": 27336, "water": 25.7, "senators":["John Kerry", "Scott Brown"]}`)
    var object interface{}
    if err := json.Unmarshal(MA, &object); err != nil {
        fmt.Println(err)
    } else {
        jsonObject := object.(map[string]interface{}) //将object类型转换成 map[string]interface{}
        fmt.Println(jsonObjectAsString(jsonObject))
    }
}

//将map中的interface{}类型值转换为实际类型的值
func jsonObjectAsString(jsonObject map[string]interface{}) string {
    var buffer bytes.Buffer
        buffer.WriteString("{")
    comma := ""
    for key, value := range jsonObject {
        buffer.WriteString(comma)
        switch value := value.(type) { //影子变量
        case nil:
            fmt.Fprintf(&buffer, "%q: null", key)
        case bool:
            fmt.Fprintf(&buffer, "%q: %t", key, value)
        case float64:
            fmt.Fprintf(&buffer, "%q: %f", key, value)
        case string:
            fmt.Fprintf(&buffer, "%q: %q", key, value)
        case []interface{}:
            fmt.Fprintf(&buffer, "%q: [", key)
            innerComma := ""
            for _, s := range value {
                if s, ok := s.(string); ok {
                    fmt.Fprintf(&buffer, "%s%q", innerComma, s)
                    innerComma = ", "
                }
            }
            buffer.WriteString("]")

        }
        comma = ", "
    }
    buffer.WriteString("}")
    return buffer.String()
}

上面的例子给出了如何反序列化一个其内部结构未知的原始json对象,如何创建和打印json对象的字符串表示。

输出打印

"{name": "Massachusetts", "area": 27336.000000, "water": 25.700000, "senators": ["John Kerry", "Scott Brown"]}

参考文档:

GO语言程序设计(作者:Mark Summerfield 译者: 许式伟、吕桂华、徐立、何李石)5.2章节。


以上所述就是小编给大家介绍的《golang进阶之路》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

通灵芯片

通灵芯片

Daniel Hillis / 崔良沂 / 上海世纪出版集团 / 2009-1 / 19.80元

本书深入浅出地阐述了计算机科学中许多基本而重要的概念,包括布尔逻辑、有限自动机、编程语言、图灵机的普遍性、信息论、算法、并行计算、量子计算、神经网络、机器学习乃至自组织系统。 作者高屋建瓴式的概括,既不失深度,又妙趣横生,相信读者读后会有很多启发。 目录: 序言:石的奇迹 第一章 通用件 第二章 万能积木 第三章 程序设计 第四章 图灵机的普适性 第......一起来看看 《通灵芯片》 这本书的介绍吧!

XML、JSON 在线转换
XML、JSON 在线转换

在线XML、JSON转换工具

RGB HSV 转换
RGB HSV 转换

RGB HSV 互转工具

RGB CMYK 转换工具
RGB CMYK 转换工具

RGB CMYK 互转工具