如果函数的参数是值传递,那么参数就是实参的一份拷贝。
比如函数的参数是一个数组,那么该数组就是源数组的拷贝。
如果是一个切片,那么该切片也是源切片的拷贝,但是这俩切片的指针指向同一块空间,所以可以通过形参修改源切片中数组的值,但是不能修改源切片的成员信息,比如len和cap。

如果是传指针的话,则可以修改实参

函数的参数可以是不定长参数,这些参数会以切片的形式进行传入。

在go语言中函数也被当做一种数据类型。


闭包有点类似于C++中static修饰局部变量,都是延长变量的生命周期。

func sub() func() {
i := 10
fmt.Println(&i)
b := func() {
fmt.Println(&i) //闭包中复制了i的指针
i-- //在b函数中引用了变量i
fmt.Println(i)
}
return b
}
func main() {
b := sub()
b()
b()
}


func defer_exe_time() (i int) {
i = 9
defer func() {
fmt.Printf("1 i=%d\n", i)//i是返回时的i,也就是5
}()
defer func(i int) {
fmt.Printf("2 i=%d\n", i)//i是注册时的i
}(i)
defer fmt.Printf("3 i=%d\n", i) //9
return 5
}
func main() {
defer_exe_time()
}





go语言中没有C++中继承和多态等机制,它通过接口来实现多态。


一个结构体只要实现了接口中的方法,这个结构体就可以被这个接口对象赋值。
接口指向不同的结构体,就可以实现多态的功能。
type Transporter interface {
move(int, int) (int, error)
whilst() error
}
type A interface {
goo()
Transporter //继承Transporter接口
}
type Car struct {
price int
power float32
}
func (car Car) whilst() error {
fmt.Println("whilst")
fmt.Printf("价格:%d,动力:%f\n", car.price, car.power)
return errors.New("123")
}
func (car Car) move(a int, b int) (int, error) {
return a + b, nil
}
func (car Car) walk() {
fmt.Println("I'm walking")
}
func (car Car) goo() {
fmt.Println("I'm going")
}
func main() {
var ifc Transporter
c := Car{10, 1.1}
ifc = &c
ifc.whilst()
ifc.move(1, 2)
c.whilst()
c.move(1, 2)
var a A
a = c
a.goo()
}





由于空接口可以传入任意类型的数据,所以就需要类型断言来判断传入的数据类型。


电商推荐流程如下:首先会按照商品的属性进行召回商品,然后根据商品的属性进行排序,再过滤掉不符合要求的商品。召回和过滤有多个,所以我们可以采用接口来实现。


推荐引擎,里面是接口的切片:




下面是该商品推荐系统的结构:

package common
type Product struct {
Id int
Name string
Size int
Sale int //销量
ShipAddress string //发货地址
Price float64
PositiveRatio float64 //好评率
RatioCount int //评论量
}
package recall
import "test10.18/common"
type Recaller interface {
Recall(n int) []*common.Product
Name() string
}
package recall
import (
"sort"
"test10.18/common"
)
var allProducts = []*common.Product{
{Id: 1, Size: 100, Sale: 38, Name: "p1"},
{Id: 2, Size: 1000, Sale: 44, Name: "p2"},
{Id: 3, Size: 50, Sale: 555, Name: "p3"},
{Id: 4, Size: 105, Sale: 11, Name: "p4"},
{Id: 5, Size: 20, Sale: 2, Name: "p5"},
{Id: 6, Size: 1550, Sale: 888, Name: "p6"},
{Id: 7, Size: 1250, Sale: 9999, Name: "p7"},
{Id: 8, Size: 1240, Sale: 444, Name: "p8"},
{Id: 9, Size: 1201, Sale: 11, Name: "p9"},
{Id: 10, Size: 1052, Sale: 10000, Name: "p10"},
}
// 按照热度召回
type HotRecall struct {
Tag string
}
func (r HotRecall) Name() string {
return r.Tag
}
func (r HotRecall) Recall(n int) []*common.Product {
sort.Slice(allProducts, func(i, j int) bool {
//销量从大到小排序
return allProducts[i].Sale > allProducts[j].Sale
})
rect := make([]*common.Product, 0, n)
for _, product := range allProducts {
rect = append(rect, product)
if len(rect) >= n {
break
}
}
return rect
}
package recall
import (
"test10.18/common"
)
// 按照热度召回
type SizeRecall struct {
Tag string
}
func (r SizeRecall) Name() string {
return r.Tag
}
func (r SizeRecall) Recall(n int) []*common.Product {
//将size小于200的商品进行召回
rect := make([]*common.Product, 0, n)
for _, product := range allProducts {
if product.Size < 200 {
rect = append(rect, product)
if len(rect) >= n {
break
}
}
}
return rect
}
package sort
import "test10.18/common"
type Sorter interface {
Sort([]*common.Product) []*common.Product
Name() string
}
package sort
import (
"sort"
"test10.18/common"
)
type RatioSorter struct {
Tag string
}
func (self RatioSorter) Name() string {
return self.Tag
}
func (self RatioSorter) Sort(products []*common.Product) []*common.Product {
sort.Slice(products, func(i, j int) bool {
return products[i].PositiveRatio > products[j].PositiveRatio
})
return products
}
package sort
import (
"sort"
"test10.18/common"
)
type SizeSorter struct {
Tag string
}
func (self SizeSorter) Name() string {
return self.Tag
}
func (self SizeSorter) Sort(products []*common.Product) []*common.Product {
sort.Slice(products, func(i, j int) bool {
return products[i].Size > products[j].Size
})
return products
}
package filter
import "test10.18/common"
// 过滤接口
type Filter interface {
Filter([]*common.Product) []*common.Product
Name() string
}
package filter
import "test10.18/common"
type RatioFilter struct {
Tag string
}
func (self RatioFilter) Name() string {
return self.Tag
}
func (self RatioFilter) Filter(products []*common.Product) []*common.Product {
rect := make([]*common.Product, 0, len(products))
for _, product := range products {
if product.RatioCount >= 0 && product.PositiveRatio >= 0 {
rect = append(rect, product)
}
}
return rect
}
package main
import (
"fmt"
"log"
"test10.18/common"
"test10.18/filter"
"test10.18/recall"
"test10.18/sort"
"time"
)
type Recommender struct {
Recallers []recall.Recaller
Sorter sort.Sorter
Filters []filter.Filter
}
func (rec *Recommender) Rec() []*common.Product {
RecallMap := make(map[int]*common.Product, 100)
//顺序遍历每一路的召回
for _, recaller := range rec.Recallers {
begin := time.Now()
products := recaller.Recall(10)
log.Printf("召回%s耗时%dns,召回了%d个商品\n", recaller.Name(), time.Since(begin).Nanoseconds(), len(products))
for _, product := range products {
RecallMap[product.Id] = product
}
}
log.Printf("一共召回了%d个商品\n", len(RecallMap))
RecallSice := make([]*common.Product, 0, len(RecallMap))
for _, product := range RecallMap {
RecallSice = append(RecallSice, product)
}
//召回完以后,对召回结果进行排序
begin := time.Now()
SortedResult := rec.Sorter.Sort(RecallSice)
log.Printf("排序耗时%dns\n", time.Since(begin).Nanoseconds())
//排完序以后进行过滤
FilteredResult := SortedResult
prevCount := len(FilteredResult)
for _, filter := range rec.Filters {
begin := time.Now()
FilteredResult = filter.Filter(FilteredResult)
log.Printf("过滤规则%s耗时%dns,过滤掉了%d个商品\n", filter.Name(), time.Since(begin).Nanoseconds(), prevCount-len(FilteredResult))
prevCount = len(FilteredResult)
}
return FilteredResult
}
func main() {
recer := Recommender{
Recallers: []recall.Recaller{
recall.HotRecall{"hot"},
recall.SizeRecall{"size"},
},
Sorter: sort.RatioSorter{Tag: "tatio"},
Filters: []filter.Filter{
filter.RatioFilter{"ratio"},
},
}
result := recer.Rec()
for i, product := range result {
fmt.Printf("第%d名:%d %s\n", i, product.Id, product.Name)
}
}
运行结果:
