Go语言类型断言、类型选择、指针、数组的问题以及生成二进制可执行文件去部署项目
类型断言
类型断言 提供了访问接口值底层具体值的方式。
t := i.(T)
该语句断言接口值 i
保存了具体类型 T
,并将其底层类型为 T
的值赋予变量 t
。
若 i
并未保存 T
类型的值,该语句就会触发一个panic
错误。
为了 判断 一个接口值是否保存了一个特定的类型,类型断言可返回两个值:其底层值以及一个报告断言是否成功的布尔值。
t, ok := i.(T)
若 i
保存了一个 T
,那么 t
将会是其底层值,而 ok
为 true
。
否则,ok
将为 false
而 t
将为 T
类型的零值,程序并不会产生panic
。
例:
package main
import "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)
}
运行结果:
hello
hello true
0 false
panic: interface conversion: interface {} is string, not float64
goroutine 1 [running]:
main.main()
/tmp/sandbox028318339/prog.go:17 +0x1f4
类型选择
类型选择 是一种按顺序从几个类型断言中选择分支的结构。
类型选择与一般的 switch 语句相似,不过类型选择中的 case 为类型(而非值), 它们针对给定接口值所存储的值的类型进行比较。
switch v := i.(type) {
case T:
// v 的类型为 T
case S:
// v 的类型为 S
default:
// 没有匹配,v 与 i 的类型相同
}
类型选择中的声明与类型断言 i.(T)
的语法相同,只是具体类型 T
被替换成了关键字 type
。
此选择语句判断接口值 i
保存的值类型是 T
还是 S
。在 T
或 S
的情况下,变量 v
会分别按 T
或 S
类型保存 i
拥有的值。在默认(即没有匹配)的情况下,变量 v
与 i
的接口类型和值相同。
例:
package main
import "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 long
I don't know about type bool!
Program exited.
Stringer
type Stringer interface {
String() string
}
Stringer
是一个可以用字符串描述自己的类型。fmt
包(还有很多包)都通过此接口来打印值。
# 官网api介绍
type Stringer
type Stringer interface {
String() string
}
Stringer 接口由任何拥有 String 方法的值所实现,该方法定义了该值的“原生”格式。 String 方法用于打印值,该值可作为操作数传至任何接受字符串的格式,或像 Print 这样的未格式化打印器。
例:
package main
import "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 main
import (
"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=amd64
set GOOS=linux
go build -o ds-customers main.go
之后上传到Linux上:
chmod +x ds-customers
执行:
./ds-customers
Go语言数组的问题
直接上代码
var group []string
group[0]="abc"
fmt.Println(group[0])123
编译正常,运行报错如下
panic: runtime error: index out of range
goroutine 1 [running]:
panic(0x47a880, 0xc42000a110)
/opt/tools/go1.7.3/src/runtime/panic.go:500 +0x1a1
main.main()
/opt/IdeaProjects/test-embeded-struct/main.go:11 +0x14
exit status 212345678
index越界,于是改了一下代码
var group []string
fmt.Println(len(group))
fmt.Println(cap(group))
group[0]="abc"
fmt.Println(group[0])12345
输出如下
0
0
panic: runtime error: index out of range
goroutine 1 [running]:
panic(0x48fec0, 0xc42000a110)
/opt/tools/go1.7.3/src/runtime/panic.go:500 +0x1a1
main.main()
/opt/IdeaProjects/test-embeded-struct/main.go:13 +0x10a
exit 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 []string
fmt.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
输出
0
0
1
1
abc12345
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
- 本文标签: Golang
- 本文链接: http://www.lzhpo.com/article/144
- 版权声明: 本文由lzhpo原创发布,转载请遵循《署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0)》许可协议授权