golang进阶之路

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

内容简介: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进阶之路》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

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

像计算机科学家一样思考Python

像计算机科学家一样思考Python

(美)Allen B.Downey / 赵普明 / 人民邮电出版社 / 2013-8 / 49

《像计算机科学家一样思考python》按照培养读者像计算机科学家一样的思维方式的思路来教授python语言编程。全书贯穿的主体是如何思考、设计、开发的方法,而具体的编程语言,只是提供一个具体场景方便介绍的媒介。《像计算机科学家一样思考python》并不是一本介绍语言的书,而是一本介绍编程思想的书。和其他编程设计语言书籍不同,它不拘泥于语言细节,而是尝试从初学者的角度出发,用生动的示例和丰富的练习来......一起来看看 《像计算机科学家一样思考Python》 这本书的介绍吧!

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

在线XML、JSON转换工具

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

RGB CMYK 互转工具