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

查看所有标签

猜你喜欢:

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

PHP 5完全攻略

PHP 5完全攻略

杜江 / 2010-5 / 79.00元

《PHP 5完全攻略(畅销书升级版)》是目前第一本真正介绍PHP 5及MySQL 5新增语法与功能的中文版本权威宝典!《PHP 5完全攻略(畅销书升级版)》本着精、全、要三宗旨,从理论中延伸,从实践中深入,翔实并完善地描述了PHP 5的开发特性与MySQL 5数据库。《PHP 5完全攻略(畅销书升级版)》分为两大部分,第1部分主要阐述PHP开发的基础知识,如PHP数组与表单处理、PHP 5面向对象......一起来看看 《PHP 5完全攻略》 这本书的介绍吧!

RGB转16进制工具
RGB转16进制工具

RGB HEX 互转工具

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

在线XML、JSON转换工具

HEX HSV 转换工具
HEX HSV 转换工具

HEX HSV 互换工具