Golang中处理接口(Interface)遇到问题如何解决

Golang中处理接口(Interface)遇到问题如何解决 我编写了以下代码,目前运行正常:

package main

import "fmt"

type T interface {
}

type hashable interface {
	Len() int
	Less() bool
	Swap()
}

type hashMapX struct {
	m map[hashable]hashable
	k []hashable
}

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

// Methods required to enable sort: Len, Less, Swap > start
func (h *hashMap) Len() int {
	return len(h.m)
}

func (h *hashMap) Less(i, j int) bool {
	switch v := h.m[h.k[i]].(type) {
	case int:
		return v > h.m[h.k[j]].(int)
	case float32:
		return v > h.m[h.k[j]].(float32)
	case float64:
		return v > h.m[h.k[j]].(float64)
	case string:
		return v > h.m[h.k[j]].(string)
	default:
		return false
	}
}

func (h *hashMap) Swap(i, j int) {
	h.k[i], h.k[j] = h.k[j], h.k[i]
}

// Methods required to enable sort: Len, Less, Swap > end

// Build Ordered Map methods
func (h *hashMap) from(m map[T]T) hashMap {
	h.m = m
	h.k = make([]T, 0, len(m))
	for key := range m {
		h.k = append(h.k, key)
	}
	return *h
}

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

我想将 空接口类型 T interface {} 替换为类似这样的定义:

type T interface {
     Len() int
     Less() bool
     Swap()
}

我该如何实现?


更多关于Golang中处理接口(Interface)遇到问题如何解决的实战教程也可以访问 https://www.itying.com/category-94-b0.html

5 回复

我没看到有任何东西阻止你这样做。

更多关于Golang中处理接口(Interface)遇到问题如何解决的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


hyousef:

替换它

你想替换什么?你是想把 hashable 重命名为 T 吗?

想要替换空的接口类型 T interface {}

// 想要替换
type T interface {
}

// 替换为
type T interface {
     Len() int
     Less() bool
     Swap()
}

你能详细说明一下你想做什么、尝试了什么以及哪里出了问题吗?以下是我的操作步骤:

  1. 我将你的代码放到了 Go Playground 中。

  2. 然后我让 T 实现了 hashable 接口中的方法,因为我认为这是你想要的效果。我通过移除 T 的实现部分来做到这一点: image

  3. 接着我尝试运行程序,但它没有成功,因为 hashMapX 引用了我刚删除的 hashable,所以我删除了 hashMapXimage

  4. 然后我再次尝试运行你的程序,这次我得到了这些错误:

    ./prog.go:23:2: impossible type switch case: h.m[h.k[i]] (type T) cannot have dynamic type int (missing Len method)
    ./prog.go:24:25: impossible type assertion:
    	int does not implement T (missing Len method)
    ./prog.go:25:2: impossible type switch case: h.m[h.k[i]] (type T) cannot have dynamic type float32 (missing Len method)
    ./prog.go:26:25: impossible type assertion:
    	float32 does not implement T (missing Len method)
    ./prog.go:27:2: impossible type switch case: h.m[h.k[i]] (type T) cannot have dynamic type float64 (missing Len method)
    ./prog.go:28:25: impossible type assertion:
    	float64 does not implement T (missing Len method)
    ./prog.go:29:2: impossible type switch case: h.m[h.k[i]] (type T) cannot have dynamic type string (missing Len method)
    ./prog.go:30:25: impossible type assertion:
    	string does not implement T (missing Len method)
    ./prog.go:53:35: cannot use "first:" (type string) as type T in map key:
    	string does not implement T (missing Len method)
    ./prog.go:53:35: cannot use 1 (type int) as type T in map value:
    	int does not implement T (missing Len method)
    ./prog.go:53:35: too many errors
    

    这行不通,因为正如错误信息所说,intfloat32float64string 没有 T 定义的方法。

    到这里我不知道接下来该怎么做,因为我不理解你的目标。

T 看起来既是你的 hashMap 的键类型,也是值类型。你可以做的一件事是创建你自己的类型来实现 T,这样你就可以在 hashMap 中使用它们,但我仍然不明白目标是什么:

type Int int

func (i Int) Len() int { /* TODO */ }
func (i Int) Less() bool { /* TODO */ }
func (i Int) Swap() { /* TODO */ }

但我不确定获取一个 IntLen 意味着什么,或者 LessSwap 在这里应该做什么。

你能重新阐述一下你的问题吗?

要实现将空接口替换为自定义接口,需要确保所有使用该接口的类型都实现了接口定义的方法。以下是修改后的代码:

package main

import "fmt"

type T interface {
    Len() int
    Less() bool
    Swap()
}

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

// 基础类型需要实现T接口
type ComparableInt int
type ComparableString string
type ComparableFloat32 float32
type ComparableFloat64 float64

func (c ComparableInt) Len() int {
    return 0
}

func (c ComparableInt) Less() bool {
    return false
}

func (c ComparableInt) Swap() {
}

func (c ComparableString) Len() int {
    return 0
}

func (c ComparableString) Less() bool {
    return false
}

func (c ComparableString) Swap() {
}

func (c ComparableFloat32) Len() int {
    return 0
}

func (c ComparableFloat32) Less() bool {
    return false
}

func (c ComparableFloat32) Swap() {
}

func (c ComparableFloat64) Len() int {
    return 0
}

func (c ComparableFloat64) Less() bool {
    return false
}

func (c ComparableFloat64) Swap() {
}

// Methods required to enable sort: Len, Less, Swap > start
func (h *hashMap) Len() int {
    return len(h.m)
}

func (h *hashMap) Less(i, j int) bool {
    switch v := h.m[h.k[i]].(type) {
    case ComparableInt:
        return int(v) > int(h.m[h.k[j]].(ComparableInt))
    case ComparableFloat32:
        return float32(v) > float32(h.m[h.k[j]].(ComparableFloat32))
    case ComparableFloat64:
        return float64(v) > float64(h.m[h.k[j]].(ComparableFloat64))
    case ComparableString:
        return string(v) > string(h.m[h.k[j]].(ComparableString))
    default:
        return false
    }
}

func (h *hashMap) Swap(i, j int) {
    h.k[i], h.k[j] = h.k[j], h.k[i]
}

// Methods required to enable sort: Len, Less, Swap > end

// Build Ordered Map methods
func (h *hashMap) from(m map[T]T) hashMap {
    h.m = m
    h.k = make([]T, 0, len(m))
    for key := range m {
        h.k = append(h.k, key)
    }
    return *h
}

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

另一种更简洁的实现方式,使用类型断言来检查接口实现:

package main

import "fmt"

type Comparable interface {
    Len() int
    Less() bool
    Swap()
}

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

// Methods required to enable sort: Len, Less, Swap > start
func (h *hashMap) Len() int {
    return len(h.m)
}

func (h *hashMap) Less(i, j int) bool {
    // 通过类型断言获取具体类型进行比较
    switch v := h.m[h.k[i]].(type) {
    case int:
        return v > h.m[h.k[j]].(int)
    case float32:
        return v > h.m[h.k[j]].(float32)
    case float64:
        return v > h.m[h.k[j]].(float64)
    case string:
        return v > h.m[h.k[j]].(string)
    default:
        return false
    }
}

func (h *hashMap) Swap(i, j int) {
    h.k[i], h.k[j] = h.k[j], h.k[i]
}

// Build Ordered Map methods
func (h *hashMap) from(m map[Comparable]Comparable) hashMap {
    h.m = m
    h.k = make([]Comparable, 0, len(m))
    for key := range m {
        h.k = append(h.k, key)
    }
    return *h
}

// 包装函数,将基础类型转换为Comparable
func NewHashMapFromMap(m map[interface{}]interface{}) *hashMap {
    hm := &hashMap{
        m: make(map[Comparable]Comparable),
        k: make([]Comparable, 0),
    }
    
    for key, value := range m {
        hm.m[key.(Comparable)] = value.(Comparable)
        hm.k = append(hm.k, key.(Comparable))
    }
    return hm
}

func main() {
    // 注意:这里需要确保传入的值实现了Comparable接口
    inv := NewHashMapFromMap(map[interface{}]interface{}{
        "first:": 1,
        "second": 2,
    })
    fmt.Printf("%v", inv)
}

关键点:

  1. 定义接口T包含Len(), Less(), Swap()方法
  2. 所有使用该接口的类型必须实现这三个方法
  3. 基础类型需要通过类型包装或类型断言来满足接口要求
  4. hashMap结构体中的map[T]T现在要求键和值都实现T接口
回到顶部