こういうことができたらいいなと言う発想から考えています。
contract ptr(t T) {
*t
}
type Ptr struct {
v reflect.Value
}
func PointerOf(type P ptr) (v P) Ptr {
return Ptr{v: reflect.ValueOf(v)}
}
func (p Ptr) Elem() reflect.Value {
return p.v.Elem()
}
以下の定義には、フィールドが関数の場合を含む。
contract Stringer(t T) {
// フィールドかメソッドか分からない
t.String()
}
contract Stringer(t T) {
var _ interface{
String() string
} = t
}
以下の定義には、メソッドも含む。
contract Field(t T) {
// メソッドも含むからダメ
t.Foo
}
メソッドは代入できないので、代入する。
contract Field(t T) {
t.Foo = t.Foo
}
型アサーションができるのはインタフェースのみに限定される。
contract Interface (_ T) {
T.(struct{})
}
len
にポインタを渡せるのは、配列のみ。
contract Array(_ T) {
len(&T{})
}
append
が呼べるのはスライスのみ。
contract Slice(t T) {
append(t, t...)
}
delete
に渡せるのはマップのみ、型が分からないのでfor range
を使う。
contract Map(t T) {
for k, _ := range t {
delete(t, k)
}
}
受信してみる。型は分からないので受け取らない。
contract Receivable(t T) {
<-t
}
close
できるのは送信可能なチャネル。
受信のみのチャネルはclose
に渡すとコンパイルエラー。
contract Sendable(t T) {
close(t)
}
アドレス演算の*
が使えるのはポインタのみ。
contract Pointer(t T) {
*t
}
contract NamedType(_ T) {
var _ struct {
T
}
}
contract NeqT1T2(_ T1, _ T2) {
var _ struct {
T1
T2
}
}
contract NotBuiltin(_ T) {
var _ struct {
int;int8;int16;int32;int64
uint;uint8;uint16;uint32;uint64
uintptr;byte;rune
float32;float64
complex64;complex128
string
bool
error
T
}
}
その場で作った型は他から参照できない。
contract Deprecated(t T) {
type D struct{}
var _ D = t
}
- 呼び出すには引数が必要
- 組み込み関数で構造体だけを対象にしたものがない
T{}
みたいな初期化は配列やスライスなどでも可能==
は配列でも使える- フィールドが関数やスライスだと
==
が使えない
- フィールドが関数やスライスだと