Golang中使用函数式选项替代方法的实践探讨

Golang中使用函数式选项替代方法的实践探讨 我尝试了以下代码,效果很好:

package main

import "fmt"

type T interface {
}

type hashMap struct {
	m    map[T]T
	k    []T
}

func (h *hashMap) From(m map[T]T) {
	h.m = m
	h.k = make([]T, len(m))
	i := 0
	for key := range m {
		h.k[i] = key
		i++
	}
}

func main() {
	inv := new(hashMap)
	inv.From(map[T]T{"first": 1})
	fmt.Printf("%v", inv)
}

输出结果符合预期:

&{map[first:1] [first]}

我正在寻找一种写法,能够实现:

inv := new(hashMap).from(map[T]T{"first": 1})
// 而不是:
//	inv := new(hashMap)
//	inv.From(map[T]T{"first": 1})

因此,我将代码重写如下:

package main

import "fmt"

type T interface {
}

type hashMap struct {
	m    map[T]T
	k    []T
	from func(m map[T]T) hashMap    // <---- 新增
} 

func from(m map[T]T) hashMap {        // <----- 函数签名变更
	h := new(hashMap)
	h.m = m
	h.k = make([]T, len(m))
	i := 0
	for key := range m {
		h.k[i] = key
		i++
	}
	return *h
}

func main() {
	inv := new(hashMap).from(map[T]T{"first": 1})
	fmt.Printf("%v", inv)
}

但我得到了以下输出:

panic: runtime error: invalid memory address or nil pointer dereference
[signal 0xc0000005 code=0x0 addr=0x0 pc=0x49c2c2]

goroutine 1 [running]:
main.main()
	d:/goplay/hashmap.go:55 +0xf2
exit status 2

有什么办法能实现我想要的写法吗?


更多关于Golang中使用函数式选项替代方法的实践探讨的实战教程也可以访问 https://www.itying.com/category-94-b0.html

1 回复

更多关于Golang中使用函数式选项替代方法的实践探讨的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


要实现链式调用,可以使用函数式选项模式。以下是修改后的代码:

package main

import "fmt"

type T interface{}

type hashMap struct {
    m map[T]T
    k []T
}

// 返回*hashMap以支持链式调用
func (h *hashMap) From(m map[T]T) *hashMap {
    h.m = m
    h.k = make([]T, len(m))
    i := 0
    for key := range m {
        h.k[i] = key
        i++
    }
    return h
}

func main() {
    // 现在可以链式调用
    inv := new(hashMap).From(map[T]T{"first": 1})
    fmt.Printf("%v", inv)
}

如果希望使用函数式选项模式进行更灵活的配置:

package main

import "fmt"

type T interface{}

type hashMap struct {
    m map[T]T
    k []T
}

type Option func(*hashMap)

func WithMap(m map[T]T) Option {
    return func(h *hashMap) {
        h.m = m
        h.k = make([]T, len(m))
        i := 0
        for key := range m {
            h.k[i] = key
            i++
        }
    }
}

func NewHashMap(opts ...Option) *hashMap {
    h := &hashMap{}
    for _, opt := range opts {
        opt(h)
    }
    return h
}

func main() {
    // 使用函数式选项
    inv := NewHashMap(WithMap(map[T]T{"first": 1}))
    fmt.Printf("%v", inv)
    
    // 支持多个选项的扩展
    inv2 := NewHashMap(
        WithMap(map[T]T{"first": 1, "second": 2}),
    )
    fmt.Printf("%v", inv2)
}

输出:

&{map[first:1] [first]}
&{map[first:1 second:2] [first second]}
回到顶部