1. 函数一等公民
- 函数可以返回多个值
- 所有参数都值传递,与java相同
- 函数可以作为变量的值,与java对比,lambda
- 函数可以作为参数和返回值
2. 可变参数
语法ops ... type
3. defer
延迟执行,类似于java的finally
4. 练习代码1
```bash package fn
import ( “fmt” “math/rand” “testing” “time” )
func returnMultiValues() (int, int) { return rand.Intn(10), rand.Intn(10) }
func TestReturnMultiValues(t *testing.T) { a, b := returnMultiValues() t.Log(a, b) }
func timeSpent(inner func(op string) int) func(op string) int { return func(str string) int { start := time.Now() ret := inner(str) fmt.Println(“time spent:”, time.Since(start).Seconds()) return ret } }
func slowFunc(str string) int { time.Sleep(time.Second * 1) return len(str) }
func TestTimeSpent(t *testing.T) { outer := timeSpent(slowFunc) t.Log(outer(“hello”)) }
func sum(ops …int) int { ret := 0 for _, op := range ops { ret += op } return ret }
func TestSum(t *testing.T) { t.Log(sum(1, 2, 3, 4), sum(2, 3, 4, 5, 6, 7)) }
func cleanResource(){ fmt.Println(“clean resources!”) }
func TestCleanResource(t *testing.T){ defer cleanResource() t.Log(“start”) panic(“发生了异常”) //t.Log(“end”) }
<a name="jYPy1"></a>
## 5. 封装数据和行为>>对象
类型定义
```go
type TypeName struct{
Id string
Name string
Age int
}
行为定义1
func (t TypeName) String{
fmt.Printf("Address is %x", unsafe.Pointer(&e.Name))
return fmt.Sprintf("ID:%s/Name:%s/Age:%d", e.Id, e.Name, e.Age)
}
行为定义2
func (t *TypeName) String{
fmt.Printf("Address is %x", unsafe.Pointer(&e.Name))
return fmt.Sprintf("ID:%s/Name:%s/Age:%d", e.Id, e.Name, e.Age)
}
6. 接口
接口与实现没有绑定关系,实现仅需要实现与接口的方法签名完全相同的方法,就表示实现与接口的关系。
type MyProgrammer interface {
WriteHello() string
}
type MyGoProgrammer struct {
}
func (gop *MyGoProgrammer) WriteHello() string{
return "fmt.Println(\"hello world!\")"
}
func TestClient1(t *testing.T){
var p MyProgrammer
p = new(MyGoProgrammer)
t.Log(p.WriteHello())
}
7. 自定义类型
type aliasInt int
8. 不支持继承只支持复合
type Pet struct {
}
func (p *Pet) Speak() {
fmt.Print("...")
}
func (p *Pet) SpeakTo(host string) {
p.Speak()
fmt.Println(" ", host)
}
type Dog struct {
//匿名属性
Pet
p *Pet
}
func (d *Dog) Speak() {
// 复合调用
fmt.Print(d.p.Speak())
fmt.Print("Wang!")
}
func TestDog(t *testing.T) {
dog := new(Dog)
dog.SpeakTo("Chao")
}
9. 空接口
空接口相当于java的Object类型,代指所有类型。
// p 是一个空接口,表示任何类型
p interface{}
// 获取p的类型
p.(type)
func DoSomething(p interface{}) {
// if i, ok := p.(int); ok {
// fmt.Println("Integer", i)
// return
// }
// if s, ok := p.(string); ok {
// fmt.Println("stirng", s)
// return
// }
// fmt.Println("Unknow Type")
switch v := p.(type) {
case int:
fmt.Println("Integer", v)
case string:
fmt.Println("String", v)
default:
fmt.Println("Unknow Type")
}
}
func TestEmptyInterfaceAssertion(t *testing.T) {
DoSomething(10)
DoSomething("10")
}
10. Go接口最佳实践
- 倾向于使用小的接口定义,Go语言很多接口都只包含一个方法
较大的接口定义,可以由多个小接口定义组合而成
type Reader interface {
Read(p []byte) (n int, err error)
}
type Writer interface {
Write(p []byte) (n int, err error)
}
type ReadWriter interface {
Reader
Writer
}
只依赖于必要功能的最小接口