[go]interface

interface基础

//介绍和定义
  接口定义来对象的行为规范, 只定义,不实现
  具体的对象实现规范细节

//接口是一组方法签名的集合
type Animal interface {
	Talk()
	Eat() int
	Run()
}
//一个对象只要包含接口中的所有方法,那么就实现来这个接口
//接口类型的变量, 可以保存具体类型的实例
type people interface {
	say()
}

type user struct {
}

func (u user) say() {
	fmt.Println("user say")
}

func main() {
	var u user

	var p people
	p = u
	p.say()
}
//接口应用实例
1.公司每个部门员工都有计算薪水的方法,但是计算方法不同
2.日志输入console,文件等方式
//空接口和类型断言
// 空接口没有定义任何方法
type A interface {

}

func main() {
	var a A
}
//接口类型实例值是nil
func main() {
	var a interface{}
	fmt.Println(a)
}

//<nil>
func main() {
	var a interface{} = 10
	fmt.Println(a)
}

//10
//空接口可以存任意类型的值
func main() {
	var a interface{}

	b:=1
	c:=false
	a = b
	fmt.Println(a)
	a = c
	fmt.Println(a)
}

//1
//false
//空接口类型作为map的key: 可接收任意类型的值
//空接口类型作为函数的参数: 可接收任意类型的值
func test(a interface{}) {
	fmt.Println(a)
}
func main() {
	test(1)
	test(false)
}

//1
//false
//获取接口类型里具体的值

func test(i interface{}) {
	s := i.(int) //get the underlying int value from i
	fmt.Println(s)
}

func main() {
	var a interface{} = 10
	test(a)
}

//10
//获取接口类型存储的值

func test(i interface{}) {
	s := i.(int) //get the underlying int value from i
	fmt.Println(s)
}

func main() {
	var a interface{} = "hel"
	test(a)
}

//panic: interface conversion: interface {} is string, not int
// 类型断言: ok机制: 判断空接口里存储的类型

func test(i interface{}) {
	v, ok := i.(int) //get the underlying int value from i
	if ok {
		fmt.Println(v)
	}
}

func main() {
	var a interface{} = "hel"
	test(a)
}
//类型断言: switch
func test(i interface{}) {
	switch i.(type) {
	case int:
		fmt.Println(i.(int))
	case string:
		fmt.Println(i.(string))
	default:
		fmt.Println("unkown type")
	}
}

func main() {
	var a interface{} = 10
	test(a)

	var b interface{} = "hi"
	test(b)
}

//10
//hi

interface使用例子

//日志库例子: 没有接口约束的情况

type ConsoleLog struct {
}

func NewConsoleLog() *ConsoleLog {
	return &ConsoleLog{}
}

func (c *ConsoleLog) LogConsoleDebug(msg interface{}) {
	fmt.Println(msg)
}

type FileLog struct {
}

func NewFileLog() *FileLog {
	return &FileLog{}
}

func (c *FileLog) LogFileDebug(msg interface{}) {
	fmt.Println(msg)
}

func main() {
	console := NewConsoleLog()
	console.LogConsoleDebug("console: test log")

	file := NewFileLog()
	file.LogFileDebug("file: test log")
}
//日志库例子: 有接口约束的情况, 切换log更加方便

type LogInterface interface {
	Debug(msg interface{})
}

type ConsoleLog struct {
}

func NewConsoleLog() LogInterface { //返回类型是接口
	return &ConsoleLog{}
}

func (c *ConsoleLog) Debug(msg interface{}) {
	fmt.Println(msg)
}

type FileLog struct {
}

func NewFileLog() LogInterface {
	return &FileLog{}
}

func (c *FileLog) Debug(msg interface{}) {
	fmt.Println(msg)
}

func main() {
	log := NewConsoleLog()
	log.Debug("console: test log")

	log = NewFileLog()
	log.Debug("file: test log")
}

输出日志

//输出日志到console
msg := fmt.Sprintf(format, args...) //format里的坑  args解出的数据相匹配
fmt.Fprintf(os.Stdout, "%s
", msg)


//输出日志到文件
file, _ := os.OpenFile("/tmp/test.log", os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0755)
fmt.Fprintf(file, "name: %s
", "maotai")

异步写日志

//将日志写入chan
select {
case f.LogDataChan <- logData:
default:
}

//从chan中去除日志写到文件
for logData := range f.LogDataChan {
    fmt.Fprintf(file, "%s %s (%s:%s:%d) %s
", logData.TimeStr, logData.LevelStr, logData.Filename, logData.FuncName, logData.LineNo, logData.Message)
}
//写日志核心逻辑

func main() {
	ch := make(chan int, 10)
	//异步写日志

	//读日志
	go func() {
		for v := range ch {
			fmt.Println(v)
		}
	}()

	for {//防止子协程退出
		select {
		case ch <- 1:
		default: //管道满了则丢弃日志,防止程序夯住
		}
		time.Sleep(time.Second)
	}
}

原文地址:https://www.cnblogs.com/iiiiiher/p/12005041.html