Go语言学习04-函数
函数是一等公民
<font color="Blue">
与其他主要编程语言的差异</font>
- 可以有多个返回值
- 所有参数都是值传递: slice, map, channel 会有传引用的错觉
- 函数可以作为变量的值
- 函数可以作为参数和返回值
学习函数式编程
可变参数
func sum(ops ...int) int {
s := 0
for _, op := range ops {
s += op
}
return s
}
defer 函数
func TestDefer(t *testing.T) {
defer func() {
t.Log("Clear resources")
}()
t.Log("Started")
panic("Fatal error") // defer仍会执行
}
Go语言学习05-面向对象编程
Go语言官方对于Go 语言是否为面向对象编程的描述https://golang.org/doc/faq:
Is Go an object-oriented language?
Yes and no. Although Go has types and methods and allows an object-oriented style of programming, there is no type hierarchy. The concept of “interface” in Go provides a different approach that we believe is wasy to use and in some ways more general.
Also, the lack of a type hierarchy makes “objects” in Go fell much more lightweight than in language such as C++ or Java.
封装数据和行为
结构体定义
type Employee struct {
Id string
Name string
Age int
}
实例创建及初始化
e := Employee{"0", "Bob", 20}
e1 := Employee{Name: "Mike", Age:30}
e2 := new(Employee) // 注意这里返回的引用/指针, 相当于 e:=&EmployeeP{}
e2.Id = "2" // 与其他编程语言的差异: 通过实例的指针访问成员不需要->
e2.Age = 22
e2.Name = "Rose"
行为 (方法) 定义
// 第一种定义方式在实例对应方法被调用时, 实例的成员会进行值复制
func (e Employee) String() string {
return fmt.Sprintf("ID:%s-Name:%s-Age:%d", e.Id, e.Name, e.Age)
}
// 通常情况下为了避免内存拷贝我们使用第二种定义方式
func (e *Employee) String() string {
return fmt.Sprintf("ID:%s-Name:%s-Age:%d", e.Id, e.Name, e.Age)
}
接口与依赖
// Programmer.java
public interface Programmer {
String WriteCodes();
}
// GoProgrammer.java
public class GoProgrammer implements Programmer{
@Override
public String WriteCodes() {
return "fmt.Println(\"Hello World!\")";
}
}
// Task.java
public class Task {
public static void main(String[] args) {
Programmer prog = new GoProgrammer();
String codes = prog.WriteCodes();
System.out.printlv(codes);
}
}
Duck Type式接口实现
接口定义
type Programmer interface {
WriteHelloWorld() Code
}
接口实现
type GoProgrammer struct {
}
func (p *GoProgrammer) WriteHelloWorld() Code {
return "fmt.Printlv(\"Hello World!\")"
}
Go 接口
与其他主要编程语言的差异
- 接口为非入侵性, 实现不依赖于接口定义
- 所以接口的定义可以包含在接口使用者包内
接口变量
自定义类型
type IntConvertionFn func(n int) int
type Mypoint int
多态
空接口与断言
-
空接口可以表示任何类型
-
通过断言来将空接口转换为指定类型
v, ok := p.(int) //ok = true 时为转换成功
Go 接口最佳实践
-
倾向于使用小的接口定义, 很多接口只包含一个方法
type Reader interface { Read(p []byte) (n int, err int) } type Writer interface { Write(p []byte) (n int, err int) }
-
较大的接口定义, 可以由多个小接口定义组合而成
type ReadWriter interface { Reader Writer }
-
只依赖于必要功能的最小接口
func StoreData(reader Reader) error { ... }