Golang 学习手册
  • 主页
  • 安装
  • 参考资料
  • Q&A
  • 基础
    • Hello,world!
    • 包
    • 变量
    • 常量
    • 类型
      • 整型
      • 浮点型
      • 复数
      • 布尔型
      • 字符
      • 字符串
      • 数组
      • 切片
      • 字典
      • 指针
      • 方法
      • 结构体
      • 接口
      • 自定义类型
    • 语法
      • 判断
      • 循环
      • 错误处理
    • 协程
      • 锁
      • 等待组
      • 通道
      • 上下文
    • 测试与分析
      • 单元测试
      • 性能测试
      • 性能分析
    • 编译
      • 条件编译
      • 交叉编译
  • 高级
    • 存储
      • 键值存储
        • Etcd
    • HTTP
      • http服务基础
      • Websocket
      • 开源框架
        • Beego
        • Echo
        • Gin
        • Iris
        • Revel
        • 框架对比
      • Kubernetes风格API框架
    • RPC
      • RPCX
      • GRPC
      • grpc-gateway
    • 连接分发器
    • TLS加密
    • 链路追踪
      • skywalking
  • 项目管理
    • 代码规范
    • 包管理
    • 文档
      • GoDoc
      • Markdown
      • Swagger
    • 仓库管理
      • 分支管理
      • 问题管理
      • 里程碑管理
      • 发布管理
    • 持续集成
      • CircleCI
      • TravisCI
由 GitBook 提供支持
在本页
  • 空接口
  • 类型接口
  • 类型推断

这有帮助吗?

在Git上编辑
  1. 基础
  2. 类型

接口

关键字interface{}

空接口

可以将所有的类型变量赋值给空接口,空接口可以进行类型断言,再转换为具体的类型变量

定义空接口的格式:

var 变量名 interface{}

例子:空接口赋值与类型推断

package main

import (
	"fmt"
)

func main() {
	// 定义并赋值一个变量v1
	var v1 int = 54

	// 将变量赋值给一个空接口i1
	var i1 interface{} = v1

	// 定义一个变量v2
	var v2 int
	// 对空接口i1进行类型推断,推断成功的话会把值赋给变量v2
	v2, _ = i1.(int)

	fmt.Println(v2)
}

以上代码的运行结果:

54

类型接口

接口可用于定义一套标准的可操作行为规范,其中包含了各种方法的定义规范。与其他语言不同,golang的接口是一种非侵入式的接口,在类型定义的过程中中不需要知道接口的存在,只会在接口赋值时去判断类型与接口是否匹配。通过这种非侵入式的接口可以更进一步地对代码进行解耦。

定义接口的格式:

type 类型名称 interface {
    方法名(传入参数)返回参数
    ...
}

例子:接口调用

package main

import (
	"fmt"
)

// 定义一个Runner接口,其中包含Run()方法
type Runner interface {
	Run()
}

// 定义一个Swimmer接口,其中包含Swim()方法
type Swimmer interface {
	Swim()
}

// 定义一个Cat类型
type Cat struct{}

// Cat类型实现了Run方法,说明猫是Runner
func (c Cat) Run() {
	fmt.Println("cat can run.")
}

// 定义一个Dog类型
type Dog struct{}

// Dog类型实现了Run方法,说明狗是Runner
func (d Dog) Run() {
	fmt.Println("dog can run.")
}

// Dog类型实现了Swim方法,说明狗是Swimmer
func (d Dog) Swim() {
	fmt.Println("dog can swim.")
}

func main() {
	// 定义一个Runner接口变量runner,默认值nil
	var runner Runner
	// 定义一个Swimmer接口变量swimmer,默认值nil
	var swimmer Swimmer

	// 实例化一个Cat类型变量cat
	var cat Cat
	// 实例化一个Dog类型变量dog
	var dog Dog

	// 将cat赋值给接口runner
	runner = cat
	// 通过runner执行cat的Run()方法
	runner.Run()

	// 将dog赋值给接口runner
	runner = dog
	// 通过runner执行dog的Run()方法
	runner.Run()

	// 将dog赋值给接口swimmer
	swimmer = dog
	// 通过swimmer执行dog的Swim()方法
	swimmer.Swim()
}

以上代码的执行结果:

cat can run.
dog can run.
dog can swim.

可以这么理解,接口只关心类型能否去执行某个方法,而不会去关心类型中有什么值

类型推断

将接口类型变量转换成其它类型需要使用类型推断,有三种书写方式:

方式一

{{ 推断后的变量 }} := {{ 接口变量 }}.({{ 推断类型 }})

使用该方式需要确保推断类型是正确的,否则会引发panic错误

方式二

{{ 推断后的变量 }}, {{ 是否推断成功 }} := {{ 接口变量 }}.({{ 推断类型 }})

方式三

switch {{ 推断后的变量 }}:={{ 接口变量 }}.(type){
case {{ 推断类型1 }}:
    ...
case {{ 推断类型2 }}:
    ...
default:
    ...
}

对于参数类型不确定的情况,推荐使用方式三

例子:通过类型推断对接口变量进行格式转换

package main

import "fmt"

func main() {
	var i interface{}
	
	// 类型推断方式一
	i = 666
	var v1 int
	v1 = i.(int)
	fmt.Printf("int:%d\n", v1)
	
	// 类型推断方式二
	i = "hello"
	var v2 string
	v2, ok := i.(string)
	if !ok{
		panic("not a string type")
	}
	fmt.Printf("string:%s\n", v2)
	
	// 类型推断方式三
	i = 3.1415926
	var v3 float64
	switch v:=i.(type){
	case float64:
		v3 = v
	default:
		panic("not type of float64")
	}	
	fmt.Printf("float:%f\n", v3)
}
上一页结构体下一页自定义类型

最后更新于4年前

这有帮助吗?