从而让*Integer既存在Less(),又存在Add(),满足券商股票交易券商股票交易接口私募,接口私募,券商股票交易接口私募,接口LessAdder
券商股票交易券商股票交易接口私募,接口私募,券商股票交易接口私募,接口是一种抽象的类型,描述了一系列方法的集合,作用是对一系列具有联系的方法做出抽象和概括。券商股票交易券商股票交易接口私募,接口私募,券商股票交易接口私募,接口只定义方法名和参数,而不包含具体的实现,这种抽象的方式可以让程序变得更加灵活更加通用。
可以看到,我们需要先定义三个方法:
Go语言中任何对象实例都满足空券商股票交易券商股票交易接口私募,接口私募,券商股票交易接口私募,接口interface{},所以可以把interface{}看作可以指向任何对象的Any类型,当函数可以接受任意的对象实例时,我们会将其声明为interface{},从而可以接受任意类型的对象,然后再使用类型断言来对该参数进行转换,再做后续的处理。
完成后,打印students,我们就可以看到排好序的列表了。
券商股票交易券商股票交易接口私募,接口私募,券商股票交易接口私募,接口是golang封装性的重要一环,券商股票交易券商股票交易接口私募,接口私募,券商股票交易接口私募,接口可以封装具体类型和类型的值,即使一个类型还有别的方法,券商股票交易券商股票交易接口私募,接口私募,券商股票交易接口私募,接口的实例也只能调用券商股票交易券商股票交易接口私募,接口私募,券商股票交易接口私募,接口暴露出来的方法。如下:
type HelloInterface interface {
Hello()
}
type User struct {
}
func (f *User) Hello() {
fmt.Println('hello')
}
func (f *User) Bye() {
fmt.Println('bye')
}
func InterfaceTest() {
u := &User{}
u.Hello() // ok
u.Bye() // ok
var user HelloInterface = new(User) // 券商股票交易券商股票交易接口私募,接口私募,券商股票交易接口私募,接口实例化
user.Hello() // ok
user.Bye() // Compile error: user.Bye undefined (type HelloInterface has no field or method Bye)
}
要将对象实例赋值给券商股票交易券商股票交易接口私募,接口私募,券商股票交易接口私募,接口,要求该对象实例实现了券商股票交易券商股票交易接口私募,接口私募,券商股票交易接口私募,接口要求的所有方法。如:
type Integer int
func (a Integer) Less(b Integer) bool {
return a < b
}
func (a *Integer) Add(b Integer) {
*a += b
}
type LessAdder interface {
Less(b Integer) bool
Add(b Integer)
}
var a Integer = 1
var b LessAdder = &a
将一个券商股票交易券商股票交易接口私募,接口私募,券商股票交易接口私募,接口赋值给另一个券商股票交易券商股票交易接口私募,接口私募,券商股票交易接口私募,接口
注意,使用一个券商股票交易券商股票交易接口私募,接口私募,券商股票交易接口私募,接口对象必须要先实例化,否则券商股票交易券商股票交易接口私募,接口私募,券商股票交易接口私募,接口对象的值为nil,调用nil对象的任何方法都会产生空指针panic。
我们需要定义一种类型,这种类型要同时具有以上三种方法,比如一个简单的Student类
type Student struct {
ID int64
Name string
}
type StudentSlice []*Student
func (s StudentSlice) Len() int {
return len(s)
}
func (s StudentSlice) Less(i, j int) bool {
return s[i].ID < s[j].ID
}
func (s StudentSlice) Swap(i, j int) {
s[i], s[j] = s[j], s[i]
}
在Go语言中,只要两个券商股票交易券商股票交易接口私募,接口私募,券商股票交易接口私募,接口拥有相同的方法列表(不用考虑顺序),那么它们就是等同的,可以相互赋值。
package one
type ReadWriter1 interface {
Read(buf []byte) (n int, err error)
Write(buf []byte) (n int, err error)
}
// 第二个券商股票交易券商股票交易接口私募,接口私募,券商股票交易接口私募,接口位于另一个包中:
package two
type ReadWriter2 interface {
Write(buf []byte) (n int, err error)
Read(buf []byte) (n int, err error)
}
// 可以相互赋值
var file1 two.ReadWriter2 = new(File)
var file2 one.ReadWriter1 = file1
var file3 two.ReadWriter2 = file2
和查询某个元素是否在map中类似,Golang也内置了券商股票交易券商股票交易接口私募,接口私募,券商股票交易接口私募,接口查询,可以使用和map类似的语法来检查对象实例是否实现了券商股票交易券商股票交易接口私募,接口私募,券商股票交易接口私募,接口,如下:
var user HelloInterface = new(User) // 券商股票交易券商股票交易接口私募,接口私募,券商股票交易接口私募,接口实例化
if u1, ok := user.(HelloInterface); ok {
fmt.Println(u1) // yes
}
if u2, ok := user.(Reader); ok {
fmt.Println(u2) // no
}
计算列表长度的方法比较两个元素的方法交换两个元素的方法
准备工作已经做好,接下来我们先来看一下sort.Sort函数的源码
// Sort sorts data.
// It makes one call to data.Len to determine n, and O(n*log(n)) calls to
// data.Less and data.Swap. The sort is not guaranteed to be stable.
func Sort(data Interface) {
n := data.Len()
quickSort(data, 0, n, maxDepth(n))
}
可以看到,函数的入参是一个sort.Interface类型的对象,然后对这个对象进行快排操作,要使用这个函数,我们还需要把[]*Student类型转换成StudentSlice,由于StudentSlice实现了sort.Interface的所有方法,所以StudentSlice的对象就是sort.Interface类型的对象。
券商股票交易券商股票交易接口私募,接口私募,券商股票交易接口私募,接口组合
type Reader interface {
Read(p []byte) (n int, err error)
}
type Writer interface {
Write(p []byte) (n int, err error)
}
// 将 Read 和 Write 方法组合
// ReadWriter 券商股票交易券商股票交易接口私募,接口私募,券商股票交易接口私募,接口既能做 Reader 券商股票交易券商股票交易接口私募,接口私募,券商股票交易接口私募,接口的所有事情,又能做 Writer 券商股票交易券商股票交易接口私募,接口私募,券商股票交易接口私募,接口的所有事情。
type ReadWriter interface {
Reader
Writer
}
// 与下面的写法完全等价
type ReadWriter interface {
Read(p []byte) (n int, err error)
Write(p []byte) (n int, err error)
}
券商股票交易券商股票交易接口私募,接口私募,券商股票交易接口私募,接口查询
接下来,让我们通过介绍内置的sort包来加深一下对券商股票交易券商股票交易接口私募,接口私募,券商股票交易接口私募,接口的理解,顺便了解一下这个常用包的使用。
在很多语言中,券商股票交易券商股票交易接口私募,接口私募,券商股票交易接口私募,接口都是侵入式的,侵入式券商股票交易券商股票交易接口私募,接口私募,券商股票交易接口私募,接口的意思是实现类需要明确声明自己实现了某个券商股票交易券商股票交易接口私募,接口私募,券商股票交易接口私募,接口,这就带来了一个很矛盾的问题,比如A调用了B的券商股票交易券商股票交易接口私募,接口私募,券商股票交易接口私募,接口,那么A一定会希望券商股票交易券商股票交易接口私募,接口私募,券商股票交易接口私募,接口被设计成自己想要使用的样子,但是B才是券商股票交易券商股票交易接口私募,接口私募,券商股票交易接口私募,接口的实现方,基于模块设计的单向依赖原则,B在实现自身的业务时,不应该关心某个具体使用方的要求,一个券商股票交易券商股票交易接口私募,接口私募,券商股票交易接口私募,接口被定义的时候,并不知道自己的方法会被谁实现,也不知道会被怎么样实现。侵入式券商股票交易券商股票交易接口私募,接口私募,券商股票交易接口私募,接口一直是面向对象编程中一个经常遭受质疑的特性。
我们可以直接使用这些方法对基本类型slice进行排序,如:
ids := []int{5,1,7,1,3,8,7,4}
names := []string{'qqq', 'www', 'ee', 'aa', 'rr', 'ba'}
sort.Ints(ids)
sort.Strings(names)
fmt.Println(ids) // [1 1 3 4 5 7 7 8]
fmt.Println(names) // [aa ba ee qqq rr www]
go语言的源码中大量使用到了券商股票交易券商股票交易接口私募,接口私募,券商股票交易接口私募,接口,比如说在前面的文章中多次使用到的error类型
// The error built-in interface type is the conventional interface for
// representing an error condition, with the nil value representing no error.
type error interface {
Error() string
}
券商股票交易券商股票交易接口私募,接口私募,券商股票交易接口私募,接口赋值并不要求两个券商股票交易券商股票交易接口私募,接口私募,券商股票交易接口私募,接口必须等价。如果券商股票交易券商股票交易接口私募,接口私募,券商股票交易接口私募,接口A的方法列表是券商股票交易券商股票交易接口私募,接口私募,券商股票交易接口私募,接口B的方法列表的子集,那么券商股票交易券商股票交易接口私募,接口私募,券商股票交易接口私募,接口B可以赋值给券商股票交易券商股票交易接口私募,接口私募,券商股票交易接口私募,接口A,但是A不可以赋值给B。
券商股票交易券商股票交易接口私募,接口私募,券商股票交易接口私募,接口
券商股票交易券商股票交易接口私募,接口私募,券商股票交易接口私募,接口定义
/* 定义券商股票交易券商股票交易接口私募,接口私募,券商股票交易接口私募,接口 */
type interface_name interface {
method_name1(input_paras...) [return_type]
method_name2(input_paras...) [return_type]
method_name3(input_paras...) [return_type]
}
/* 定义结构体 */
type struct_name struct {
/* variables */
}
/* 实现券商股票交易券商股票交易接口私募,接口私募,券商股票交易接口私募,接口方法 */
func (struct_name_variable struct_name) method_name1(input_paras...) [return_type] {
/* 方法实现 */
}
func (struct_name_variable struct_name) method_name2(input_paras...) [return_type] {
/* 方法实现*/
}
func (struct_name_variable struct_name) method_name3(input_paras...) [return_type] {
/* 方法实现*/
}
首先我们要先了解sort.Interface源码中定义了哪些方法:
// A type, typically a collection, that satisfies sort.Interface can be
// sorted by the routines in this package. The methods require that the
// elements of the collection be enumerated by an integer index.
type Interface interface {
// Len is the number of elements in the collection.
Len() int
// Less reports whether the element with
// index i should sort before the element with index j.
Less(i, j int) bool
// Swap swaps the elements with indexes i and j.
Swap(i, j int)
}
最典型的例子是标准库fmt中PrintXXX系列的函数,例如:
也可以查询对象是否是某个类型
if u3, ok := user.(*User); ok {
fmt.Println(u3)
}
将对象实例赋值给券商股票交易券商股票交易接口私募,接口私募,券商股票交易接口私募,接口
Any类型
注意,此处赋值时用&a而不是a,因为Go会自动为*Integer生成一个新的Less方法
func (a *Integer) Less(b Integer) bool {
return (*a).Less(b)
}
封装性
Golang还可以使用断言和反射来进行类型查询,这两个内容会在后续的文章中介绍。
券商股票交易券商股票交易接口私募,接口私募,券商股票交易接口私募,接口概念
不同的是,golang的券商股票交易券商股票交易接口私募,接口私募,券商股票交易接口私募,接口是一种非侵入式的券商股票交易券商股票交易接口私募,接口私募,券商股票交易接口私募,接口,一个类型不需要明确声明,只要实现了券商股票交易券商股票交易接口私募,接口私募,券商股票交易接口私募,接口的所有方法,这个类型就实现了该券商股票交易券商股票交易接口私募,接口私募,券商股票交易接口私募,接口,这个类型的对象就是这个券商股票交易券商股票交易接口私募,接口私募,券商股票交易接口私募,接口类型的实例。在golang中,不再需要定义类的继承关系,而且在定义券商股票交易券商股票交易接口私募,接口私募,券商股票交易接口私募,接口时候,只需要关心自己需要提供哪些方法,其他的方法有使用方按需定义即可。
券商股票交易券商股票交易接口私募,接口私募,券商股票交易接口私募,接口赋值
接下来,对一个Student进行初始化
s1 := &Student{
ID: 1,
Name: 'A',
}
s2 := &Student{
ID: 2,
Name: 'B',
}
s3 := &Student{
ID: 3,
Name: 'C',
}
students := []*Student{s3, s1, s2}
Golang的sort包中通过券商股票交易券商股票交易接口私募,接口私募,券商股票交易接口私募,接口的方式内置了可以对任何类型的列表进行快排的功能,下面我们一起来看看它是如何使用的。
文章为作者独立观点,不代表股票交易接口观点