C++角度的go模板特性|青训营笔记

127 阅读2分钟

这是我参与[第五届青训营]的第八天

golang语言是开源、强类型、面向对象、编译型、内存安全和类型安全的一门可扩展的、并行的、简洁的现代式语言。

然而,在实际应用中由于效能和共用性,会同其他语言一起使用,比如C++、C。Golang内建垃圾回收机制,并且无法移除,因此对于性能要求高的系统语言等,使用不方便。Golang的库文件基本只能Golang可以使用,输出C API的功能不是很好。

以下是在golang中使用C接口的方法示例:

package point /* 1 */  
// #include "point.h" /* 2 */ 
import "C" /* 3 */ 
import "unsafe" /* 4 */ 
type Point struct { /* 5 */ 
    point *C.point_t /* 6 */ 
} /* 7 */ 
func NewPoint(x float64, y float64) *Point { /* 8 */ 
    pt := new(Point) /* 9 */ 
    pt.point = C.point_new(C.double(x), C.double(y)) /* 10 */ 
    return pt /* 11 */ 
} /* 12 */ 
func (pt *Point) Delete() { /* 13 */     
    C.point_delete(unsafe.Pointer(pt.point)) /* 14 */ 
} /* 15 */ 
func (pt *Point) X() float64 { /* 16 */ 
    return float64(C.point_x(pt.point)) /* 17 */ 
} /* 18 */ 
func (pt *Point) Y() float64 { /* 19 */ 
    return float64(C.point_y(pt.point)) /* 20 */ 
} /* 21 */ 
func Distance(p *Point, q *Point) float64 { /* 22 */ 
    return float64(C.point_distance(p.point, q.point)) /* 23 */ 
}

该程式码定义了C语言中的使用指针的point结构体,并提供了对应的内存申请和删除操作,基本的构造函数等。

在golang中,模板如下对照

// cpp
#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);
}

golang中对照为:

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)
}

以上方法使用了自定义的Identified结构体进行了模板的类似实现。并定义了类型T接口。