内容简介:golang的接口使用非常广泛,几乎每一个包都会用到接口,fmt包的使用率最多之一。在实际开发中,要定义结构体的标准输出用String(),定义标准错误输出Error(),定义格式化输出Format(),还有比较特殊的GoString()。接下来描述接口的使用方式,使用场景,还有注意的地方。使用起来比较简单,只要结构体里面有
golang的接口使用非常广泛,几乎每一个包都会用到接口,fmt包的使用率最多之一。在实际开发中,要定义结构体的标准输出用String(),定义标准错误输出Error(),定义格式化输出Format(),还有比较特殊的GoString()。接下来描述接口的使用方式,使用场景,还有注意的地方。
String()
type TestString struct {} func (t TestString) String() string { return "我是String" } func main() { fmt.Println(TestString{}) } 复制代码
我是String 复制代码
使用起来比较简单,只要结构体里面有 String() string
就可以输出。
fmt
包里面会判断有没有 fmt.Stringer
的接口,然后再调用。
通常用于结构体的默认输出,例如:
type Student struct { number int realname string age int } func main() { stu := &Student{ number: 1, realname: "王小明", age: 18, } fmt.Println(stu) } 复制代码
&{1 王小明 18} 复制代码
改成:
type Student struct { number int realname string age int } func (t *Student) String() string { return fmt.Sprintf("学号: %d\n真实姓名: %s\n年龄: %d\n", t.number, t.realname, t.age) } func main() { stu := &Student{ number: 1, realname: "王小明", age: 18, } fmt.Println(stu) } 复制代码
学号: 1 真实姓名: 王小明 年龄: 18 复制代码
瞬间感觉高大上了吧!!
Error
type TestError struct {} func (t TestError) Error() string { return "我是Error" } func main() { fmt.Println(TestString{}) } 复制代码
我是Error 复制代码
实际上使用方式跟 String()
一样,但是设计代码时不能互相替换实现。
最常用的用法是独立封装 type XXXError struct{}
,在文章最尾会揣摸一下为什么要这样用。
Format
type TestFormat struct {} func (t TestFormat) Format(s fmt.State, c rune) { switch c { case 'c': switch { case s.Flag('+'): fmt.Printf("我是+c\n") default: fmt.Fprint(s, "我是c\n") } default: fmt.Print("我是Format") } } func main() { t := TestFormat{} fmt.Println(t) fmt.Printf("%c\n", t) fmt.Printf("%+c\n", t) fmt.Printf("%s\n", t) } 复制代码
我是Format 我是c 我是+c 我是Format 复制代码
fmt.Println
也会调用Format的接口,所以 String()
Format()
不能同一个结构体里面。
通常使用跟 Error()
类似,可以参考一下 github.com/pkg/errors
里的 stack.go
的 func (f Frame) Format(s fmt.State, verb rune)
GoString
type TestGoString struct {} func (t TestGoString) GoString() string { return "我是GoString" } func main() { t := TestGoString{} fmt.Println(TestGoString{}) fmt.Printf("%s %#v\n", t, t) } 复制代码
{} {} 我是GoString 复制代码
如上所示 fmt.Println
并没调用GoString方法,只能通过格式化 %#
+标记输出。
在没有实现接口的情况下,通常用来输出默认相应值,如下:
func main() { var i uint = 18 // 输出十六进制 fmt.Printf("%x\n", i) fmt.Printf("%#x\n", i) } 复制代码
12 0x12 复制代码
注意事项
fmt/print.go
的 pp.handleMethods(verb rune) (handled bool)
func (p *pp) handleMethods(verb rune) (handled bool) { ... // 判断Formatter if formatter, ok := p.arg.(Formatter); ok { ... formatter.Format(p, verb) return } // 判断是否含有#标识符 if p.fmt.sharpV { // 判断GoStriner if stringer, ok := p.arg.(GoStringer); ok { ... p.fmt.fmtS(stringer.GoString()) return } } else { switch verb { case 'v', 's', 'x', 'X', 'q': switch v := p.arg.(type) { // 符合error接口 case error: ... p.fmtString(v.Error(), verb) return // 符合Stringer接口 case Stringer: ... p.fmtString(v.String(), verb) return } } } return false } 复制代码
Format -> (#)GoString -> ((v,s,x,X,q)Error -> String) 源码四个接口都在handlerMethods方法调用控制,都不是互相独立,根据优先顺序调用。所以接口的设计,尽可能独立封装,避免混淆。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- delphi – 如何检查接口对象是否实现了另一个接口?
- SpringBoot2 API接口签名实现(接口参数防篡改)
- 接口与实现分离
- 判断Golang接口是否实现
- Python实现数据驱动接口测试
- Spring应用--实现InitializingBean接口
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。