【golang】代码学习

package main

import (
    "fmt"
    "sort"
)

// A couple of type definitions to make the units clear.
type earthMass float64
type au float64

// A Planet defines the properties of a solar system object.
type Planet struct {
    name     string
    mass     earthMass
    distance au
}

// By is the type of a "less" function that defines the ordering of its Planet arguments.
type By func(p1, p2 *Planet) bool

// Sort is a method on the function type, By, that sorts the argument slice according to the function.
func (by By) Sort(planets []Planet) {
    ps := &planetSorter{
        planets: planets,
        by:      by, // The Sort method's receiver is the function (closure) that defines the sort order.
    }
    sort.Sort(ps)
}

// planetSorter joins a By function and a slice of Planets to be sorted.
type planetSorter struct {
    planets []Planet
    by      func(p1, p2 *Planet) bool // Closure used in the Less method.
}

// Len is part of sort.Interface.
func (s *planetSorter) Len() int {
    return len(s.planets)
}

// Swap is part of sort.Interface.
func (s *planetSorter) Swap(i, j int) {
    s.planets[i], s.planets[j] = s.planets[j], s.planets[i]
}

// Less is part of sort.Interface. It is implemented by calling the "by" closure in the sorter.
func (s *planetSorter) Less(i, j int) bool {
    return s.by(&s.planets[i], &s.planets[j])
}

var planets = []Planet{
    {"Mercury", 0.055, 0.4},
    {"Venus", 0.815, 0.7},
    {"Earth", 1.0, 1.0},
    {"Mars", 0.107, 1.5},
}

// ExampleSortKeys demonstrates a technique for sorting a struct type using programmable sort criteria.
func main() {
    // Closures that order the Planet structure.
    name := func(p1, p2 *Planet) bool {
        return p1.name < p2.name
    }
    mass := func(p1, p2 *Planet) bool {
        return p1.mass < p2.mass
    }
    distance := func(p1, p2 *Planet) bool {
        return p1.distance < p2.distance
    }
    decreasingDistance := func(p1, p2 *Planet) bool {
        return distance(p2, p1)
    }

    // Sort the planets by the various criteria.
    By(name).Sort(planets)
    fmt.Println("By name:", planets)

    By(mass).Sort(planets)
    fmt.Println("By mass:", planets)

    By(distance).Sort(planets)
    fmt.Println("By distance:", planets)

    By(decreasingDistance).Sort(planets)
    fmt.Println("By decreasing distance:", planets)

}

这段代码的功能无所谓,这段代码揭示了如何巧妙地设计几个排序函数,让它和系统的sort函数结合起来使用。

 

1,理解sort.Sort()

首先,sort.Sort(sortFunc),这里使用了interface{},只需要sortFunc来定义自己的实现;

sortFunc,需要定义Len, Swap, Less这三个函数

其中,Swap这个函数可以复用,Len这个函数也可以复用,但是Less这个函数需要自定义

不同的sortFunc,对应不同的Less。

 

1.1,理解sort.Less

其次,Less函数定义,不同的Less函数,对应不同的功能;

nameLess, massLess, distanceLes, decreasingDistanceLess,这表示是四个不同的Less函数;

 

2,理解planetSorter 

planetSorter相当于一个包装类,包装了两个参数:a,planets=数据本身;b,by=Less的封装;

planets好理解,是数据,只需要赋值进去就好了;

by不太好理解,by是个结构体的一部分,不同于int, float, string, []string等数据结构,它是个func;

有名函数完成定义之后(mass,name等都是有名函数),这些有名函数赋值给planetSorter.by,就可以使用了。

 

其实也可以这么用:

nameLess := name
func createSorter(planets []planet, sortLessFunc func(p1, p2 *planet) bool) *planetSorter { return &planetSorter{planets: planets, by: sortLessFunc} } sort.Sort(createSorter(planets, nameLess)) // 这就完成了排序的功能,使用的nameLess的排序,对planets数据进行排序

这样处理起来更简单,理解起来更方便;

 

我们来理解下官方的代码:

By(lessFunc).Sort(planets) // 关键语句

type By struct/func = class LessFuncType{}

 

拆分1: By 约等于类的初始化

By(lessFunc) = new LessFuncType(lessFunc) // 类似于new INT(1) (INT是int的type,使用1初始化INT类型)

拆分2: Sort函数约等于调用类的成员函数

By(lessFunc).Sort(planets) = (class LessFuncType).Sort(planets) // 调用对象的成员函数的意思,实际并不需要一定借助By来实现,只是这么实现代码量少,能利用go的一些特性

 

我们用createSorter也是可以做的,而且没有理解负担,挺好的;

 

最后

我们倾向于用我们自己的理解和实现来实现代码,而不是当前语言支持的那种方式来实现,也是ok的;并没有什么偏向;

跟 章亦春 说的一样,看ssl代码还是nginx代码来着,有很多汇编语言的风格,实际可以用C来实现也是OK的,这就是语言风格倾向的问题,没有严格的对错;

只要是实现了,就是ok的;

posted on 2021-01-07 20:53  awildfish  阅读(135)  评论(0编辑  收藏  举报

导航