Go 中类似 C++ 模板的行为

标签 c++ templates go

例如我有两个不同的结构 FooBar

struct Foo {...}
struct Bar {...}

以及基于它们构建的许多函数和其他类型。

C++ 风格:

template<typename T>
struct Identified {
    T model;
    std::string id;
};

template<typename T>
Identified<T> GetIdentifiedModel(std::string id) {
    Identified<T> result;
    T.id = id;
    T.model.set(getSomeData(id));  // Common method for T
    return result;
}

如何在 Go 中实现这些示例?

对于常用方法,接口(interface)可以完成工作,但我看不到如何从接口(interface)检索特定类型来声明它、返回它或其他任何东西,我无法再处理复制/粘贴代码:)

谢谢!

编辑@Amd:https://ideone.com/rqpsQb

#include <string>
#include <iostream>

struct Foo {
    char c;
    void set(std::string s) {c = s[0];}; // We don't really care here
};
struct Bar {
    int n;
    void set(std::string s) {n = s.size();}; // We don't really care here
};

template<typename T>
struct Identified {
    T model;
    std::string id;
};

template<typename T>
Identified<T> GetIdentifiedModel(std::string id) {
    Identified<T> result;
    result.id = id;
    // Obviously shouldn't be ID but for the example
    result.model.set(id);  // Common method for T
    return result;
}

void assert(bool b) {
    if (b) std::cout << "OK" << std::endl;
    else std::cout << "There is a problem !" << std::endl;
};

int main() {
    auto fooWithID = GetIdentifiedModel<Foo>("foo id");
    auto barWithID = GetIdentifiedModel<Bar>("bar");
    assert (fooWithID.model.c == 'f');
    assert (barWithID.model.n == 3);
    return (0);
}

最佳答案

1- 你可以使用

fooWithID := GetIdentifiedModel("foo id", &Foo{})

喜欢这个工作示例(尝试 The Go Playground):

package main

import "fmt"

type Foo struct {
    c byte
}

func (t *Foo) set(s string) { t.c = s[0] }

type Bar struct {
    n int
}

func (t *Bar) set(s string) { t.n = len(s) }

type Identified struct {
    model T
    id    string
}

func GetIdentifiedModel(id string, t T) *Identified {
    result := &Identified{model: t}
    result.id = id
    result.model.set(id)
    return result
}

func assert(b bool) {
    if b {
        fmt.Println("OK")
    } else {
        fmt.Println("There is a problem !")
    }
}

func main() {
    fooWithID := GetIdentifiedModel("foo id", &Foo{})
    barWithID := GetIdentifiedModel("bar", &Bar{})

    assert(fooWithID.model.(*Foo).c == 'f')
    assert(barWithID.model.(*Bar).n == 3)
}

type T interface {
    set(string)
}

输出:

OK
OK

2- 你可以使用(读起来很舒服:Identified model Foo):

fooWithID := GetIdentifiedModel("foo id", &Identified{model: &Foo{}})

喜欢这个工作示例(尝试 The Go Playground):

package main

import "fmt"

type Foo struct {
    c byte
}

func (t *Foo) set(s string) { t.c = s[0] }

type Bar struct {
    n int
}

func (t *Bar) set(s string) { t.n = len(s) }

type Identified struct {
    model T
    id    string
}

func GetIdentifiedModel(id string, result *Identified) *Identified {
    result.id = id
    result.model.set(id)
    return result
}

func assert(b bool) {
    if b {
        fmt.Println("OK")
    } else {
        fmt.Println("There is a problem !")
    }
}

func main() {
    fooWithID := GetIdentifiedModel("foo id", &Identified{model: &Foo{}})
    barWithID := GetIdentifiedModel("bar", &Identified{model: &Bar{}})    
    assert(fooWithID.model.(*Foo).c == 'f')
    assert(barWithID.model.(*Bar).n == 3)
}

type T interface {
    set(string)
}

输出:

OK
OK

另请参阅:One method to handle all the struct types that embed one common struct (json marshalling)

关于Go 中类似 C++ 模板的行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39559293/

相关文章:

c++ - Dlib人脸识别,多张图片检测

android - COCOS-2d-x : Idea to implement Level progress in games

c++ - 在 C++ 和 C 中共享一个结构?

c++ - 使用 -Wl,--as-needed 强制与共享库链接(仅提供模板时)

html - Template Toolkit - 在插入之前从插入的片段中获取变量

validation - 使用 goplayground 验证器库验证结构数组

c++ - 我该怎么做才能避免接收方出现 TCP 零窗口/TCP 窗口满?

go - http.ServeMux 路由挂载?

docker - 如何通过 websocket 获取 Docker 容器输出?

c++ - Boost状态图-使用状态图作为模板参数时出现编译错误