15

Go语言类型断言、类型选择、指针、数组的问题以及生成二进制可执行文件去部署项目

 4 years ago
source link: http://www.lzhpo.com/article/144
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

Go语言类型断言、类型选择、指针、数组的问题以及生成二进制可执行文件去部署项目

类型断言 提供了访问接口值底层具体值的方式。

t := i.(T)

该语句断言接口值 i 保存了具体类型 T,并将其底层类型为 T 的值赋予变量 t

i 并未保存 T 类型的值,该语句就会触发一个panic错误。

为了 判断 一个接口值是否保存了一个特定的类型,类型断言可返回两个值:其底层值以及一个报告断言是否成功的布尔值。

t, ok := i.(T)

i 保存了一个 T,那么 t 将会是其底层值,而 oktrue

否则,ok 将为 falset 将为 T 类型的零值,程序并不会产生panic

package mainimport "fmt"func main() {    var i interface{} = "hello"    s := i.(string)    fmt.Println(s)    s, ok := i.(string)    fmt.Println(s, ok)    f, ok := i.(float64)    fmt.Println(f, ok)    f = i.(float64) // 报错(panic)    fmt.Println(f)}

运行结果:

hellohello true0 falsepanic: interface conversion: interface {} is string, not float64goroutine 1 [running]:main.main()    /tmp/sandbox028318339/prog.go:17 +0x1f4

类型选择 是一种按顺序从几个类型断言中选择分支的结构。

类型选择与一般的 switch 语句相似,不过类型选择中的 case 为类型(而非值), 它们针对给定接口值所存储的值的类型进行比较。

switch v := i.(type) {case T:    // v 的类型为 Tcase S:    // v 的类型为 Sdefault:    // 没有匹配,v 与 i 的类型相同}

类型选择中的声明与类型断言 i.(T) 的语法相同,只是具体类型 T 被替换成了关键字 type

此选择语句判断接口值 i 保存的值类型是 T 还是 S。在 TS 的情况下,变量 v 会分别按 TS 类型保存 i 拥有的值。在默认(即没有匹配)的情况下,变量 vi 的接口类型和值相同。

package mainimport "fmt"func do(i interface{}) {    switch v := i.(type) {    case int:        fmt.Printf("Twice %v is %v\n", v, v*2)    case string:        fmt.Printf("%q is %v bytes long\n", v, len(v))    default:        fmt.Printf("I don't know about type %T!\n", v)    }}func main() {    do(21)    do("hello")    do(true)}

运行结果:

Twice 21 is 42"hello" is 5 bytes longI don't know about type bool!Program exited.

Stringer

fmt 包中定义的 Stringer 是最普遍的接口之一。

type Stringer interface {    String() string}

Stringer 是一个可以用字符串描述自己的类型。fmt 包(还有很多包)都通过此接口来打印值。

# 官网api介绍type Stringertype Stringer interface {    String() string}Stringer 接口由任何拥有 String 方法的值所实现,该方法定义了该值的“原生”格式。 String 方法用于打印值,该值可作为操作数传至任何接受字符串的格式,或像 Print 这样的未格式化打印器。
package mainimport "fmt"type Person struct {    Name string    Age  int}func (p Person) String() string {    return fmt.Sprintf("%v (%v years)", p.Name, p.Age)}func main() {    a := Person{"Arthur Dent", 42}    z := Person{"Zaphod Beeblebrox", 9001}    fmt.Println(a, z)}

运行结果:

Arthur Dent (42 years) Zaphod Beeblebrox (9001 years)Program exited.

Reader

io 包指定了 io.Reader 接口,它表示从数据流的末尾进行读取。

Go 标准库包含了该接口的许多实现,包括文件、网络连接、压缩和加密等等。

io.Reader 接口有一个 Read 方法:

func (T) Read(b []byte) (n int, err error)

Read 用数据填充给定的字节切片并返回填充的字节数和错误值。在遇到数据流的结尾时,它会返回一个 io.EOF 错误。

示例代码创建了一个 strings.Reader 并以每次 8 字节的速度读取它的输出。

package mainimport (    "fmt"    "io"    "strings")func main() {    r := strings.NewReader("Hello, Reader!")    b := make([]byte, 8)    for {        n, err := r.Read(b)        fmt.Printf("n = %v err = %v b = %v\n", n, err, b)        fmt.Printf("b[:n] = %q\n", b[:n])        if err == io.EOF {            break        }    }}

运行结果:

n = 8 err = <nil> b = [72 101 108 108 111 44 32 82]b[:n] = "Hello, R"n = 6 err = <nil> b = [101 97 100 101 114 33 32 82]b[:n] = "eader!"n = 0 err = EOF b = [101 97 100 101 114 33 32 82]b[:n] = ""

Go语言指针符号的*和&

&符号的意思是对变量取地址,如:变量a的地址是&a

*符号的意思是对指针取值,如:*&a,就是a变量所在地址的值,当然也就是a的值了

生成二进制可执行文件去部署项目

set GOARCH=amd64set GOOS=linuxgo build -o ds-customers main.go

之后上传到Linux上:

chmod +x ds-customers
./ds-customers

Go语言数组的问题

直接上代码

var group []stringgroup[0]="abc"fmt.Println(group[0])123

编译正常,运行报错如下

panic: runtime error: index out of rangegoroutine 1 [running]:panic(0x47a880, 0xc42000a110)    /opt/tools/go1.7.3/src/runtime/panic.go:500 +0x1a1main.main()    /opt/IdeaProjects/test-embeded-struct/main.go:11 +0x14exit status 212345678

index越界,于是改了一下代码

var group []stringfmt.Println(len(group))fmt.Println(cap(group))group[0]="abc"fmt.Println(group[0])12345
00panic: runtime error: index out of rangegoroutine 1 [running]:panic(0x48fec0, 0xc42000a110)    /opt/tools/go1.7.3/src/runtime/panic.go:500 +0x1a1main.main()    /opt/IdeaProjects/test-embeded-struct/main.go:13 +0x10aexit status 212345678910

也就是说,slice声明的时候如果不同时初始化数据,默认长度和容量都是0,下标0意味着长度是1,所以index越界了。


那么,使用slice的时候有下面几种方式


第一,声明的时候初始化数据,例如

test:=[]string{"a","b","c"}1

第二,从已经初始化数据的slice‘切’出来

test:=[]string{"a","b","c"}your_string=test[0:1]12

第三,append方法,会默认扩容,

var group []stringfmt.Println(len(group))fmt.Println(cap(group))group=append(group,"hahaha")group[0]="abc"fmt.Println(len(group))fmt.Println(cap(group))fmt.Println(group[0])12345678
0011abc12345

append方法在slice长度不足的时候,会进行扩容,注释如下

// The append built-in function appends elements to the end of a slice. If// it has sufficient capacity, the destination is resliced to accommodate the// new elements. If it does not, a new underlying array will be allocated.// Append returns the updated slice. It is therefore necessary to store the// result of append, often in the variable holding the slice itself://  slice = append(slice, elem1, elem2)//  slice = append(slice, anotherSlice...)// As a special case, it is legal to append a string to a byte slice, like this://  slice = append([]byte("hello "), "world"...)func append(slice []Type, elems ...Type) []Type
正文到此结束
所属分类:Go开发

Recommend

  • 33
    • studygolang.com 6 years ago
    • Cache

    golang: 类型转换和类型断言

    类型转换在程序设计中都是不可避免的问题。当然有一些语言将这个过程给模糊了,大多数时候开发者并不需要去关注这方面的问题。但是golang中的类型匹配是很严格的,不同的类型之间通常需要手动转换,编译器不会代你去做这个事。我之所以说...

  • 60

    通过类型断言(type assertion)方式来判断接口的具体类型, Sometimes, you may want to know the exact type of an interface variable. In this scenario, you can use type assertion : x.(T)

  • 29
    • studygolang.com 5 years ago
    • Cache

    类型转换和断言

    Golang不支持隐式类型转换 普通类型转换 普通类型转换可以转换不同但是相互兼容的类型,例如int与float,int与rune,但是string与数字类型是不能进行普通类型转换的。 例如: a = 123 x := i...

  • 46
    • Github github.com 5 years ago
    • Cache

    谈谈 TypeScript 中的类型断言

    类型断言 类型断言(Type Assertion)可以用来手动指定一个值的类型。 语法 值 as 类型 或 <类型>值 在 tsx 语法(React 的 jsx 语法的 ts 版)中必须使用前者,即

  • 19

    Hi,大家好,我是明哥。 在自己学习 Golang 的这段时间里,我写了详细的学习笔记放在我的个人微信公众号 《Go编程时光》,对于 Go 语言,我也算是个初学者,因此写的东西应该会比较适合刚接触的同学,如果你也是刚学习 Go 语言,不...

  • 39
    • studygolang.com 5 years ago
    • Cache

    Go之断言类型(assert type)

    1.背景介绍: 笔者最近在使用一个数据结构实现多个接口,但是却发现想要在一段时间内转换成接口1,另外一段时间转换成接口2,所以也就使用到了断言类型。在看过断言类型之后,觉得还是很有必要讲一讲这个断言类型,于是...

  • 22
    • studygolang.com 4 years ago
    • Cache

    聊聊golang的类型断言

    序 本文主要研究一下golang的类型断言 类型断言 x.(T) 断言x不为nil且x为T类型 如果T不是接口类型,则该断言x为T类型 如果T类接口类型,则该断言x实现了T接口

  • 14

    golang语言编译的二进制可执行文件为什么比 C 语言大 最近一位朋友问我“为什么同样的hello world 入门程序”为什么golang编译出来的二进制文件,比 C 大,而且大很多。我做了个测试,来分析这个问题。C 语言的hello world程序: ...

  • 11

    本文介绍从编译后的二进制可执行文件中解析原 Go 项目中的依赖包信息的一些方法, 解决类似:接手一个老项目但是这个老项目中又依赖了另一个老项目的二进制可执行文件, 导致无法知道这个二进制可执行文件具体是其对应源代码仓库的哪个版本的代码编译出来的尴尬...

  • 11
    • studygolang.com 3 years ago
    • Cache

    golang类型转换与断言

    golang类型转换与断言 13641329565 · 1天之前 · 100 次点击 · 预计阅读时间 1 分钟 · 大...

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK