golang中type关键字使⽤
type关键字使⽤
type是go语法⾥的重要⽽且常⽤的关键字,type绝不只是对应于C/C++中的typedef。搞清楚type的使⽤,就容易理解go语⾔中的核⼼概念struct、interface、函数等的使⽤。以下我⽤例⼦代码总结描述,请特别留意代码中的注释。
1、定义结构体
//结构体定义
type person struct {
name string//注意后⾯不能有逗号
age  int
}
func main() {
//结构体初始化
p := person{
name: "taozs", //注意后⾯要加逗号
age:  18, //或者下⾯的}提到这⼉来可以省略逗号
}
fmt.Println(p.name)
}
//初始化字段不⼀定要全部指定,⽐如下⾯也是可以的,name默认取长度为0的空字符串
p := person{
age: 18,
}
2、类型等价定义,相当于类型重命名
type name string
name类型与string等价
例⼦:
type name string
func main() {
var myname name = "taozs"//其实就是字符串类型
l := []byte(myname) //字符串转字节数组
fmt.Println(len(l)) //字节长度
}
不过,要注意的是,type绝不只是⽤于定义⼀系列的别名。还可以针对新类型定义⽅法。
上⾯的name类型可以像下⾯这样定义⽅法:
type name string
func (n name) len() int {
return len(n)
}
func main() {
var myname name = "taozs"//其实就是字符串类型
l := []byte(myname) //字符串转字节数组
fmt.Println(len(l)) //字节长度
fmt.Println(myname.len()) //调⽤对象的⽅法
}
3、结构体内嵌匿名成员
//结构体内嵌匿名成员定义
type person struct {
string//直接写类型,匿名
age int
}
func main() {
//结构体匿名成员初始化
p := person{string: "taozs", age: 18}//可以省略部分字段,如:person{string: "taozs"}。也可以这样省略字段名:person{“taozs”, 18},但必须写全了,不可以省略部分字段  //结构体匿名成员访问
fmt.Println(p.string) //注意不能⽤强制类型转换(类型断⾔):p.(string)
}
以下是只有单个匿名成员的例⼦。
//结构体内嵌匿名成员定义
type person struct {
string
}
func main() {
//结构体匿名成员初始化
p := person{string: "taozs"} //也可这样:person{"taozs"}
//结构体匿名成员访问
fmt.Println(p.string) //注意不能⽤强制类型转换(类型断⾔):p.(string)
}
4、定义接⼝类型
package main
import (
"fmt"
)
//接⼝定义
type Personer interface {
Run()
Name() string
}
//实现接⼝,注意实现接⼝的不⼀定只是结构体,也可以是函数对象,参见下⾯第5条type person struct {
name string
age  int
}
func (person) Run() {
fmt.Println("")
}
//接收参数person不可以是指针类型,否则不认为是实现了接⼝
func (p person) Name() string {
return p.name
}
func main() {
/
/接⼝类型的变量定义
var p Personer
fmt.Println(p) //值<nil>
//实例化结构体,并赋值给interface
p = person{"taozs", 18} //或者:&person{"taozs", 18}
p.Run()
fmt.Println(p.Name())
var p2 person = p.(person) //类型断⾔,接⼝类型断⾔到具体类型
fmt.Println(p2.age)
}
//另外,类型断⾔返回值也可以有第⼆个bool值,表⽰断⾔是否成功,如下:
if p2, ok := p.(person); ok {//断⾔成功ok值为true
fmt.Println(ok)
fmt.Println(p2.age)
}
5、定义函数类型
//以下是定义⼀个函数类型handler
type handler func (name string) int
//针对这个函数类型可以再定义⽅法,如:
func (h handler) add(name string) int {
return h(name) + 10
}
/
/下⾯让我们详细看⼀下例⼦,其中涉及了函数、函数的⽅法、结构体⽅法、接⼝的使⽤。
package main
import (
"fmt"
)
//定义接⼝
type adder interface {
add(string) int
}
//定义函数类型
type handler func (name string) int
/
/实现函数类型⽅法
func (h handler) add(name string) int {
return h(name) + 10
}
//函数参数类型接受实现了adder接⼝的对象(函数或结构体)
func process(a adder) {
fmt.Println("process:", a.add("taozs"))
}
//另⼀个函数定义
func doubler(name string) int {
return len(name) * 2
}
//⾮函数类型
type myint int
//实现了adder接⼝
func (i myint) add(name string) int {
return len(name) + int(i)
}
func main() {
//注意要成为函数对象必须显式定义handler类型
var my handler = func (name string) int {
return len(name)
}
//以下是函数或函数⽅法的调⽤
fmt.Println(my("taozs"))                  //调⽤函数
fmt.Println(my.add("taozs")) //调⽤函数对象的⽅法
fmt.Println(handler(doubler).add("taozs")) //doubler函数显式转换成handler函数对象然后调⽤对象的add⽅法
//
////以下是针对接⼝adder的调⽤
process(my) //process函数需要adder接⼝类型参数
//
process(handler(doubler)) //因为process接受的参数类型是handler,所以这⼉要强制转换
//
process(myint(8)) //实现adder接⼝不仅可以是函数也可以是结构体
}
熟悉了上⾯type的各种⽤法,现在来⼀起分析下http包⾥⾯的HandleFunc    type func() ⽤法分析
在看golang 的http服务部分代码时,被golang 中的 type func()写法难住了,⼀时没看懂代码。后来查资料后,有了⼀点理解。在golang中可以通过这样简单实现⼀个http服务
package main
import "net/http"
func mHttp() {
http.HandleFunc("/", h)
http.ListenAndServe("0.0.0.0:8888",nil)
func h(w http.ResponseWriter, r *http.Request) {
}
http.HandleFunc()是⼀个注册函数,传⼀个string类型的路由,和⼀个函数,函数的参数为(http.ResponseWriter, *http.Request)。跟踪进⼊函数,在golang 源码net/⽂件中
func HandleFunc(pattern string, handler func(ResponseWriter, *Request)) {
DefaultServeMux.HandleFunc(pattern, handler)
}
在HandleFunc调⽤了DefaultServeMux.HandleFunc(pattern, handler)
⾄于这些函数是⼲啥的先不做探讨,这不是本⽂的重点。
再次跟进函数
func (mux *ServeMux) HandleFunc(pattern string, handler func(ResponseWriter, *Request)) {
if handler == nil {
panic("http: nil handler")
}
mux.Handle(pattern, HandlerFunc(handler))
}
在mux.Handle(pattern, HandlerFunc(handler)) 的第⼆个参数HandlerFunc(handler)是什么⿁。
跟进看⼀下
type HandlerFunc func(ResponseWriter, *Request)
func (f HandlerFunc) ServeHTTP(w ResponseWriter, r *Request) {
f(w, r)
}
原来HandlerFunc 是⽤ type 定义的函数,⽽函数的类型就是最开始传⼊的类型func(ResponseWriter, *Request)
ServeHTTP是HandlerFunc的⼀个⽅法(注意⼀下,golang中⽅法和函数不是⼀回事)。并且HandlerFunc实现了 Handler接⼝
Handler接⼝定义:
type Handler interface {
ServeHTTP(ResponseWriter, *Request)
}
回到HandleFunc⽅法中,mux.Handle(pattern, HandlerFunc(handler))的第⼆个参数是把传⼊的函数 handler 强转成 HandlerFunc类型,这样handler 就实现了Handler接⼝。
到这我们明⽩HandlerFunc(handler)是把普通函数强转成type定义的函数。
现在写⼀个简单的demo验证⼀下:
package main
import "fmt"
func main() {
one(2, callback)
}
//需要传递函数
func callback(i int) {
fmt.Println("i am callBack")
fmt.Println(i)
}
//main中调⽤的函数
func one(i int, f func(int)) {
two(i, fun(f))
}
//one()中调⽤的函数
func two(i int, c Call) {
c.call(i)
}
//定义的type函数
type fun func(int)
//fun实现的Call接⼝的call()函数
func (f fun) call(i int) {
f(i)
}
//接⼝
type Call interface {
call(int)
}
先看⼀下程序的运⾏结果:
我们在main()函数中调⽤了one()函数,并传⼊了callback()函数,最终调⽤了我们传⼊的callback()函数。
理⼀下思路:
使⽤type定义函数 func(int)
定义 Call 接⼝,Call中有⼀个函数 call(int)
在main()中调⽤one(2, callback),在one()中调⽤two(),传⼊two()函数前,对callback函数实现了类型转换,从普通函数转换成type定义的函数。
go语言字符串转数组
在 two() 中调⽤传⼊的 c 因为 c 实现了 Call 接⼝,所以可以调⽤ call() 函数,最终调⽤了我们传⼊的 callback() 函数。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。