mirror of
https://github.com/golang/go
synced 2024-11-21 18:14:42 -07:00
cmd/gc: cache itab lookup in convT2I.
There may be further savings if convT2I can avoid the function call if the cache is good and T is uintptr-shaped, a la convT2E, but that will be a follow-up CL. src/pkg/runtime: benchmark old ns/op new ns/op delta BenchmarkConvT2ISmall 43 15 -64.01% BenchmarkConvT2IUintptr 45 14 -67.48% BenchmarkConvT2ILarge 130 101 -22.31% test/bench/go1: benchmark old ns/op new ns/op delta BenchmarkBinaryTree17 8588997000 8499058000 -1.05% BenchmarkFannkuch11 5300392000 5358093000 +1.09% BenchmarkGobDecode 30295580 31040190 +2.46% BenchmarkGobEncode 18102070 17675650 -2.36% BenchmarkGzip 774191400 771591400 -0.34% BenchmarkGunzip 245915100 247464100 +0.63% BenchmarkJSONEncode 123577000 121423050 -1.74% BenchmarkJSONDecode 451969800 596256200 +31.92% BenchmarkMandelbrot200 10060050 10072880 +0.13% BenchmarkParse 10989840 11037710 +0.44% BenchmarkRevcomp 1782666000 1716864000 -3.69% BenchmarkTemplate 798286600 723234400 -9.40% R=rsc, bradfitz, go.peter.90, daniel.morsing, dave, uriel CC=golang-dev https://golang.org/cl/6337058
This commit is contained in:
parent
917f764382
commit
18e86644a3
@ -208,7 +208,7 @@ ggloblnod(Node *nam, int32 width)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
ggloblsym(Sym *s, int32 width, int dupok)
|
ggloblsym(Sym *s, int32 width, int dupok, int rodata)
|
||||||
{
|
{
|
||||||
Prog *p;
|
Prog *p;
|
||||||
|
|
||||||
@ -220,8 +220,9 @@ ggloblsym(Sym *s, int32 width, int dupok)
|
|||||||
p->to.name = D_NONE;
|
p->to.name = D_NONE;
|
||||||
p->to.offset = width;
|
p->to.offset = width;
|
||||||
if(dupok)
|
if(dupok)
|
||||||
p->reg = DUPOK;
|
p->reg |= DUPOK;
|
||||||
p->reg |= RODATA;
|
if(rodata)
|
||||||
|
p->reg |= RODATA;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
@ -206,7 +206,7 @@ ggloblnod(Node *nam, int32 width)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
ggloblsym(Sym *s, int32 width, int dupok)
|
ggloblsym(Sym *s, int32 width, int dupok, int rodata)
|
||||||
{
|
{
|
||||||
Prog *p;
|
Prog *p;
|
||||||
|
|
||||||
@ -218,8 +218,9 @@ ggloblsym(Sym *s, int32 width, int dupok)
|
|||||||
p->to.index = D_NONE;
|
p->to.index = D_NONE;
|
||||||
p->to.offset = width;
|
p->to.offset = width;
|
||||||
if(dupok)
|
if(dupok)
|
||||||
p->from.scale = DUPOK;
|
p->from.scale |= DUPOK;
|
||||||
p->from.scale |= RODATA;
|
if(rodata)
|
||||||
|
p->from.scale |= RODATA;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
@ -207,7 +207,7 @@ ggloblnod(Node *nam, int32 width)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
ggloblsym(Sym *s, int32 width, int dupok)
|
ggloblsym(Sym *s, int32 width, int dupok, int rodata)
|
||||||
{
|
{
|
||||||
Prog *p;
|
Prog *p;
|
||||||
|
|
||||||
@ -219,8 +219,9 @@ ggloblsym(Sym *s, int32 width, int dupok)
|
|||||||
p->to.index = D_NONE;
|
p->to.index = D_NONE;
|
||||||
p->to.offset = width;
|
p->to.offset = width;
|
||||||
if(dupok)
|
if(dupok)
|
||||||
p->from.scale = DUPOK;
|
p->from.scale |= DUPOK;
|
||||||
p->from.scale |= RODATA;
|
if(rodata)
|
||||||
|
p->from.scale |= RODATA;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
@ -41,7 +41,7 @@ char *runtimeimport =
|
|||||||
"func @\"\".convI2E(@\"\".elem any) (@\"\".ret any)\n"
|
"func @\"\".convI2E(@\"\".elem any) (@\"\".ret any)\n"
|
||||||
"func @\"\".convI2I(@\"\".typ *byte, @\"\".elem any) (@\"\".ret any)\n"
|
"func @\"\".convI2I(@\"\".typ *byte, @\"\".elem any) (@\"\".ret any)\n"
|
||||||
"func @\"\".convT2E(@\"\".typ *byte, @\"\".elem any) (@\"\".ret any)\n"
|
"func @\"\".convT2E(@\"\".typ *byte, @\"\".elem any) (@\"\".ret any)\n"
|
||||||
"func @\"\".convT2I(@\"\".typ *byte, @\"\".typ2 *byte, @\"\".elem any) (@\"\".ret any)\n"
|
"func @\"\".convT2I(@\"\".typ *byte, @\"\".typ2 *byte, @\"\".cache **byte, @\"\".elem any) (@\"\".ret any)\n"
|
||||||
"func @\"\".assertE2E(@\"\".typ *byte, @\"\".iface any) (@\"\".ret any)\n"
|
"func @\"\".assertE2E(@\"\".typ *byte, @\"\".iface any) (@\"\".ret any)\n"
|
||||||
"func @\"\".assertE2E2(@\"\".typ *byte, @\"\".iface any) (@\"\".ret any, @\"\".ok bool)\n"
|
"func @\"\".assertE2E2(@\"\".typ *byte, @\"\".iface any) (@\"\".ret any, @\"\".ok bool)\n"
|
||||||
"func @\"\".assertE2I(@\"\".typ *byte, @\"\".iface any) (@\"\".ret any)\n"
|
"func @\"\".assertE2I(@\"\".typ *byte, @\"\".iface any) (@\"\".ret any)\n"
|
||||||
|
@ -767,6 +767,7 @@ EXTERN Pkg* importpkg; // package being imported
|
|||||||
EXTERN Pkg* structpkg; // package that declared struct, during import
|
EXTERN Pkg* structpkg; // package that declared struct, during import
|
||||||
EXTERN Pkg* builtinpkg; // fake package for builtins
|
EXTERN Pkg* builtinpkg; // fake package for builtins
|
||||||
EXTERN Pkg* gostringpkg; // fake pkg for Go strings
|
EXTERN Pkg* gostringpkg; // fake pkg for Go strings
|
||||||
|
EXTERN Pkg* itabpkg; // fake pkg for itab cache
|
||||||
EXTERN Pkg* runtimepkg; // package runtime
|
EXTERN Pkg* runtimepkg; // package runtime
|
||||||
EXTERN Pkg* stringpkg; // fake package for C strings
|
EXTERN Pkg* stringpkg; // fake package for C strings
|
||||||
EXTERN Pkg* typepkg; // fake package for runtime type info
|
EXTERN Pkg* typepkg; // fake package for runtime type info
|
||||||
@ -1330,7 +1331,7 @@ void gdatacomplex(Node*, Mpcplx*);
|
|||||||
void gdatastring(Node*, Strlit*);
|
void gdatastring(Node*, Strlit*);
|
||||||
void genembedtramp(Type*, Type*, Sym*, int iface);
|
void genembedtramp(Type*, Type*, Sym*, int iface);
|
||||||
void ggloblnod(Node *nam, int32 width);
|
void ggloblnod(Node *nam, int32 width);
|
||||||
void ggloblsym(Sym *s, int32 width, int dupok);
|
void ggloblsym(Sym *s, int32 width, int dupok, int rodata);
|
||||||
Prog* gjmp(Prog*);
|
Prog* gjmp(Prog*);
|
||||||
void gused(Node*);
|
void gused(Node*);
|
||||||
int isfat(Type*);
|
int isfat(Type*);
|
||||||
|
@ -204,6 +204,10 @@ main(int argc, char *argv[])
|
|||||||
gostringpkg->name = "go.string";
|
gostringpkg->name = "go.string";
|
||||||
gostringpkg->prefix = "go.string"; // not go%2estring
|
gostringpkg->prefix = "go.string"; // not go%2estring
|
||||||
|
|
||||||
|
itabpkg = mkpkg(strlit("go.itab"));
|
||||||
|
itabpkg->name = "go.itab";
|
||||||
|
itabpkg->prefix = "go.itab"; // not go%2eitab
|
||||||
|
|
||||||
runtimepkg = mkpkg(strlit("runtime"));
|
runtimepkg = mkpkg(strlit("runtime"));
|
||||||
runtimepkg->name = "runtime";
|
runtimepkg->name = "runtime";
|
||||||
|
|
||||||
|
@ -314,7 +314,7 @@ stringsym(char *s, int len)
|
|||||||
}
|
}
|
||||||
off = duint8(sym, off, 0); // terminating NUL for runtime
|
off = duint8(sym, off, 0); // terminating NUL for runtime
|
||||||
off = (off+widthptr-1)&~(widthptr-1); // round to pointer alignment
|
off = (off+widthptr-1)&~(widthptr-1); // round to pointer alignment
|
||||||
ggloblsym(sym, off, 1);
|
ggloblsym(sym, off, 1, 1);
|
||||||
|
|
||||||
return sym;
|
return sym;
|
||||||
}
|
}
|
||||||
|
@ -305,7 +305,7 @@ dimportpath(Pkg *p)
|
|||||||
p->pathsym = n->sym;
|
p->pathsym = n->sym;
|
||||||
|
|
||||||
gdatastring(n, p->path);
|
gdatastring(n, p->path);
|
||||||
ggloblsym(n->sym, types[TSTRING]->width, 1);
|
ggloblsym(n->sym, types[TSTRING]->width, 1, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
@ -857,7 +857,7 @@ ok:
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
ot = dextratype(s, ot, t, xt);
|
ot = dextratype(s, ot, t, xt);
|
||||||
ggloblsym(s, ot, dupok);
|
ggloblsym(s, ot, dupok, 1);
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -955,7 +955,7 @@ dalgsym(Type *t)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
ggloblsym(s, ot, 1);
|
ggloblsym(s, ot, 1, 1);
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -61,7 +61,7 @@ func slicestringcopy(to any, fr any) int
|
|||||||
func convI2E(elem any) (ret any)
|
func convI2E(elem any) (ret any)
|
||||||
func convI2I(typ *byte, elem any) (ret any)
|
func convI2I(typ *byte, elem any) (ret any)
|
||||||
func convT2E(typ *byte, elem any) (ret any)
|
func convT2E(typ *byte, elem any) (ret any)
|
||||||
func convT2I(typ *byte, typ2 *byte, elem any) (ret any)
|
func convT2I(typ *byte, typ2 *byte, cache **byte, elem any) (ret any)
|
||||||
|
|
||||||
// interface type assertions x.(T)
|
// interface type assertions x.(T)
|
||||||
func assertE2E(typ *byte, iface any) (ret any)
|
func assertE2E(typ *byte, iface any) (ret any)
|
||||||
|
@ -375,6 +375,7 @@ walkexpr(Node **np, NodeList **init)
|
|||||||
int64 v;
|
int64 v;
|
||||||
int32 lno;
|
int32 lno;
|
||||||
Node *n, *fn;
|
Node *n, *fn;
|
||||||
|
Sym *sym;
|
||||||
char buf[100], *p;
|
char buf[100], *p;
|
||||||
|
|
||||||
n = *np;
|
n = *np;
|
||||||
@ -755,6 +756,22 @@ walkexpr(Node **np, NodeList **init)
|
|||||||
ll = list(ll, typename(n->left->type));
|
ll = list(ll, typename(n->left->type));
|
||||||
if(!isnilinter(n->type))
|
if(!isnilinter(n->type))
|
||||||
ll = list(ll, typename(n->type));
|
ll = list(ll, typename(n->type));
|
||||||
|
if(!isinter(n->left->type) && !isnilinter(n->type)){
|
||||||
|
sym = pkglookup(smprint("%-T.%-T", n->left->type, n->type), itabpkg);
|
||||||
|
if(sym->def == N) {
|
||||||
|
l = nod(ONAME, N, N);
|
||||||
|
l->sym = sym;
|
||||||
|
l->type = ptrto(types[TUINT8]);
|
||||||
|
l->addable = 1;
|
||||||
|
l->class = PEXTERN;
|
||||||
|
l->xoffset = 0;
|
||||||
|
sym->def = l;
|
||||||
|
ggloblsym(sym, widthptr, 1, 0);
|
||||||
|
}
|
||||||
|
l = nod(OADDR, sym->def, N);
|
||||||
|
l->addable = 1;
|
||||||
|
ll = list(ll, l);
|
||||||
|
}
|
||||||
ll = list(ll, n->left);
|
ll = list(ll, n->left);
|
||||||
argtype(fn, n->left->type);
|
argtype(fn, n->left->type);
|
||||||
argtype(fn, n->type);
|
argtype(fn, n->type);
|
||||||
|
@ -183,19 +183,25 @@ copyout(Type *t, void **src, void *dst)
|
|||||||
alg->copy(size, dst, *src);
|
alg->copy(size, dst, *src);
|
||||||
}
|
}
|
||||||
|
|
||||||
// func convT2I(typ *byte, typ2 *byte, elem any) (ret any)
|
// func convT2I(typ *byte, typ2 *byte, cache **byte, elem any) (ret any)
|
||||||
#pragma textflag 7
|
#pragma textflag 7
|
||||||
void
|
void
|
||||||
runtime·convT2I(Type *t, InterfaceType *inter, ...)
|
runtime·convT2I(Type *t, InterfaceType *inter, Itab **cache, ...)
|
||||||
{
|
{
|
||||||
byte *elem;
|
byte *elem;
|
||||||
Iface *ret;
|
Iface *ret;
|
||||||
|
Itab *tab;
|
||||||
int32 wid;
|
int32 wid;
|
||||||
|
|
||||||
elem = (byte*)(&inter+1);
|
elem = (byte*)(&cache+1);
|
||||||
wid = t->size;
|
wid = t->size;
|
||||||
ret = (Iface*)(elem + ROUND(wid, Structrnd));
|
ret = (Iface*)(elem + ROUND(wid, Structrnd));
|
||||||
ret->tab = itab(inter, t, 0);
|
tab = runtime·atomicloadp(cache);
|
||||||
|
if(!tab) {
|
||||||
|
tab = itab(inter, t, 0);
|
||||||
|
runtime·atomicstorep(cache, tab);
|
||||||
|
}
|
||||||
|
ret->tab = tab;
|
||||||
copyin(t, elem, &ret->data);
|
copyin(t, elem, &ret->data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,98 +5,134 @@
|
|||||||
package runtime_test
|
package runtime_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"io"
|
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type I1 interface {
|
||||||
|
Method1()
|
||||||
|
}
|
||||||
|
|
||||||
|
type I2 interface {
|
||||||
|
Method1()
|
||||||
|
Method2()
|
||||||
|
}
|
||||||
|
|
||||||
|
type TS uint16
|
||||||
|
type TM uintptr
|
||||||
|
type TL [2]uintptr
|
||||||
|
|
||||||
|
func (TS) Method1() {}
|
||||||
|
func (TS) Method2() {}
|
||||||
|
func (TM) Method1() {}
|
||||||
|
func (TM) Method2() {}
|
||||||
|
func (TL) Method1() {}
|
||||||
|
func (TL) Method2() {}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
I interface{}
|
e interface{}
|
||||||
J int
|
e_ interface{}
|
||||||
B = new(bytes.Buffer)
|
i1 I1
|
||||||
W io.Writer = B
|
i2 I2
|
||||||
I2 interface{} = B
|
ts TS
|
||||||
R io.ReadWriter = B
|
tm TM
|
||||||
Big [2]*int
|
tl TL
|
||||||
)
|
)
|
||||||
|
|
||||||
func BenchmarkConvT2ESmall(b *testing.B) {
|
func BenchmarkConvT2ESmall(b *testing.B) {
|
||||||
for i := 0; i < b.N; i++ {
|
for i := 0; i < b.N; i++ {
|
||||||
I = uint16(1)
|
e = ts
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func BenchmarkConvT2EUintptr(b *testing.B) {
|
func BenchmarkConvT2EUintptr(b *testing.B) {
|
||||||
for i := 0; i < b.N; i++ {
|
for i := 0; i < b.N; i++ {
|
||||||
I = uintptr(1)
|
e = tm
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func BenchmarkConvT2EBig(b *testing.B) {
|
func BenchmarkConvT2ELarge(b *testing.B) {
|
||||||
v := [2]uintptr{1, 2}
|
|
||||||
for i := 0; i < b.N; i++ {
|
for i := 0; i < b.N; i++ {
|
||||||
I = v
|
e = tl
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func BenchmarkConvT2I(b *testing.B) {
|
func BenchmarkConvT2ISmall(b *testing.B) {
|
||||||
for i := 0; i < b.N; i++ {
|
for i := 0; i < b.N; i++ {
|
||||||
W = B
|
i1 = ts
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkConvT2IUintptr(b *testing.B) {
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
i1 = tm
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func BenchmarkConvT2ILarge(b *testing.B) {
|
||||||
|
for i := 0; i < b.N; i++ {
|
||||||
|
i1 = tl
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func BenchmarkConvI2E(b *testing.B) {
|
func BenchmarkConvI2E(b *testing.B) {
|
||||||
|
i2 = tm
|
||||||
for i := 0; i < b.N; i++ {
|
for i := 0; i < b.N; i++ {
|
||||||
I = W
|
e = i2
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func BenchmarkConvI2I(b *testing.B) {
|
func BenchmarkConvI2I(b *testing.B) {
|
||||||
|
i2 = tm
|
||||||
for i := 0; i < b.N; i++ {
|
for i := 0; i < b.N; i++ {
|
||||||
W = R
|
i1 = i2
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func BenchmarkAssertE2T(b *testing.B) {
|
func BenchmarkAssertE2T(b *testing.B) {
|
||||||
I = 1
|
e = tm
|
||||||
for i := 0; i < b.N; i++ {
|
for i := 0; i < b.N; i++ {
|
||||||
J = I.(int)
|
tm = e.(TM)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func BenchmarkAssertE2TBig(b *testing.B) {
|
func BenchmarkAssertE2TLarge(b *testing.B) {
|
||||||
var v interface{} = [2]*int{}
|
e = tl
|
||||||
for i := 0; i < b.N; i++ {
|
for i := 0; i < b.N; i++ {
|
||||||
Big = v.([2]*int)
|
tl = e.(TL)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func BenchmarkAssertE2I(b *testing.B) {
|
func BenchmarkAssertE2I(b *testing.B) {
|
||||||
|
e = tm
|
||||||
for i := 0; i < b.N; i++ {
|
for i := 0; i < b.N; i++ {
|
||||||
W = I2.(io.Writer)
|
i1 = e.(I1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func BenchmarkAssertI2T(b *testing.B) {
|
func BenchmarkAssertI2T(b *testing.B) {
|
||||||
|
i1 = tm
|
||||||
for i := 0; i < b.N; i++ {
|
for i := 0; i < b.N; i++ {
|
||||||
B = W.(*bytes.Buffer)
|
tm = i1.(TM)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func BenchmarkAssertI2I(b *testing.B) {
|
func BenchmarkAssertI2I(b *testing.B) {
|
||||||
|
i1 = tm
|
||||||
for i := 0; i < b.N; i++ {
|
for i := 0; i < b.N; i++ {
|
||||||
W = R.(io.Writer)
|
i2 = i1.(I2)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func BenchmarkAssertI2E(b *testing.B) {
|
func BenchmarkAssertI2E(b *testing.B) {
|
||||||
|
i1 = tm
|
||||||
for i := 0; i < b.N; i++ {
|
for i := 0; i < b.N; i++ {
|
||||||
I = R.(interface{})
|
e = i1.(interface{})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func BenchmarkAssertE2E(b *testing.B) {
|
func BenchmarkAssertE2E(b *testing.B) {
|
||||||
|
e = tm
|
||||||
for i := 0; i < b.N; i++ {
|
for i := 0; i < b.N; i++ {
|
||||||
I = I2.(interface{})
|
e_ = e
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,27 +8,56 @@
|
|||||||
|
|
||||||
package main
|
package main
|
||||||
|
|
||||||
|
type J interface {
|
||||||
|
Method()
|
||||||
|
}
|
||||||
|
|
||||||
|
type (
|
||||||
|
U16 uint16
|
||||||
|
U32 uint32
|
||||||
|
U64 uint64
|
||||||
|
U128 [2]uint64
|
||||||
|
F32 float32
|
||||||
|
F64 float64
|
||||||
|
C128 complex128
|
||||||
|
S string
|
||||||
|
B []byte
|
||||||
|
M map[int]int
|
||||||
|
C chan int
|
||||||
|
Z struct{}
|
||||||
|
)
|
||||||
|
|
||||||
|
func (U16) Method() {}
|
||||||
|
func (U32) Method() {}
|
||||||
|
func (U64) Method() {}
|
||||||
|
func (U128) Method() {}
|
||||||
|
func (F32) Method() {}
|
||||||
|
func (F64) Method() {}
|
||||||
|
func (C128) Method() {}
|
||||||
|
func (S) Method() {}
|
||||||
|
func (B) Method() {}
|
||||||
|
func (M) Method() {}
|
||||||
|
func (C) Method() {}
|
||||||
|
func (Z) Method() {}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
z = struct{}{}
|
u16 = U16(1)
|
||||||
|
u32 = U32(2)
|
||||||
|
u64 = U64(3)
|
||||||
|
u128 = U128{4, 5}
|
||||||
|
f32 = F32(6)
|
||||||
|
f64 = F64(7)
|
||||||
|
c128 = C128(8 + 9i)
|
||||||
|
s = S("10")
|
||||||
|
b = B("11")
|
||||||
|
m = M{12: 13}
|
||||||
|
c = make(C, 14)
|
||||||
|
z = Z{}
|
||||||
p = &z
|
p = &z
|
||||||
pp = &p
|
pp = &p
|
||||||
u16 = uint16(1)
|
|
||||||
u32 = uint32(2)
|
|
||||||
u64 = uint64(3)
|
|
||||||
u128 = [2]uint64{4, 5}
|
|
||||||
f32 = float32(6)
|
|
||||||
f64 = float64(7)
|
|
||||||
c128 = complex128(8 + 9i)
|
|
||||||
s = "10"
|
|
||||||
b = []byte("11")
|
|
||||||
m = map[int]int{12: 13}
|
|
||||||
c = make(chan int, 14)
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
iz interface{} = z
|
|
||||||
ip interface{} = p
|
|
||||||
ipp interface{} = pp
|
|
||||||
iu16 interface{} = u16
|
iu16 interface{} = u16
|
||||||
iu32 interface{} = u32
|
iu32 interface{} = u32
|
||||||
iu64 interface{} = u64
|
iu64 interface{} = u64
|
||||||
@ -40,6 +69,24 @@ var (
|
|||||||
ib interface{} = b
|
ib interface{} = b
|
||||||
im interface{} = m
|
im interface{} = m
|
||||||
ic interface{} = c
|
ic interface{} = c
|
||||||
|
iz interface{} = z
|
||||||
|
ip interface{} = p
|
||||||
|
ipp interface{} = pp
|
||||||
|
|
||||||
|
ju16 J = u16
|
||||||
|
ju32 J = u32
|
||||||
|
ju64 J = u64
|
||||||
|
ju128 J = u128
|
||||||
|
jf32 J = f32
|
||||||
|
jf64 J = f64
|
||||||
|
jc128 J = c128
|
||||||
|
js J = s
|
||||||
|
jb J = b
|
||||||
|
jm J = m
|
||||||
|
jc J = c
|
||||||
|
jz J = z
|
||||||
|
jp J = p // The method set for *T contains the methods for T.
|
||||||
|
// pp does not implement error.
|
||||||
)
|
)
|
||||||
|
|
||||||
func second(a ...interface{}) interface{} {
|
func second(a ...interface{}) interface{} {
|
||||||
@ -47,44 +94,78 @@ func second(a ...interface{}) interface{} {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
// Test equality. There are no tests for b and m, as slices and
|
// Test equality.
|
||||||
// maps are not comparable by ==.
|
|
||||||
if z != iz {
|
|
||||||
panic("z != iz")
|
|
||||||
}
|
|
||||||
if p != ip {
|
|
||||||
panic("p != ip")
|
|
||||||
}
|
|
||||||
if pp != ipp {
|
|
||||||
panic("pp != ipp")
|
|
||||||
}
|
|
||||||
if u16 != iu16 {
|
if u16 != iu16 {
|
||||||
panic("u16 != iu16")
|
panic("u16 != iu16")
|
||||||
}
|
}
|
||||||
|
if u16 != ju16 {
|
||||||
|
panic("u16 != ju16")
|
||||||
|
}
|
||||||
if u32 != iu32 {
|
if u32 != iu32 {
|
||||||
panic("u32 != iu32")
|
panic("u32 != iu32")
|
||||||
}
|
}
|
||||||
|
if u32 != ju32 {
|
||||||
|
panic("u32 != ju32")
|
||||||
|
}
|
||||||
if u64 != iu64 {
|
if u64 != iu64 {
|
||||||
panic("u64 != iu64")
|
panic("u64 != iu64")
|
||||||
}
|
}
|
||||||
|
if u64 != ju64 {
|
||||||
|
panic("u64 != ju64")
|
||||||
|
}
|
||||||
if u128 != iu128 {
|
if u128 != iu128 {
|
||||||
panic("u128 != iu128")
|
panic("u128 != iu128")
|
||||||
}
|
}
|
||||||
|
if u128 != ju128 {
|
||||||
|
panic("u128 != ju128")
|
||||||
|
}
|
||||||
if f32 != if32 {
|
if f32 != if32 {
|
||||||
panic("f32 != if32")
|
panic("f32 != if32")
|
||||||
}
|
}
|
||||||
|
if f32 != jf32 {
|
||||||
|
panic("f32 != jf32")
|
||||||
|
}
|
||||||
if f64 != if64 {
|
if f64 != if64 {
|
||||||
panic("f64 != if64")
|
panic("f64 != if64")
|
||||||
}
|
}
|
||||||
|
if f64 != jf64 {
|
||||||
|
panic("f64 != jf64")
|
||||||
|
}
|
||||||
if c128 != ic128 {
|
if c128 != ic128 {
|
||||||
panic("c128 != ic128")
|
panic("c128 != ic128")
|
||||||
}
|
}
|
||||||
|
if c128 != jc128 {
|
||||||
|
panic("c128 != jc128")
|
||||||
|
}
|
||||||
if s != is {
|
if s != is {
|
||||||
panic("s != is")
|
panic("s != is")
|
||||||
}
|
}
|
||||||
|
if s != js {
|
||||||
|
panic("s != js")
|
||||||
|
}
|
||||||
if c != ic {
|
if c != ic {
|
||||||
panic("c != ic")
|
panic("c != ic")
|
||||||
}
|
}
|
||||||
|
if c != jc {
|
||||||
|
panic("c != jc")
|
||||||
|
}
|
||||||
|
// There are no tests for b and m, as slices and maps are not comparable by ==.
|
||||||
|
if z != iz {
|
||||||
|
panic("z != iz")
|
||||||
|
}
|
||||||
|
if z != jz {
|
||||||
|
panic("z != jz")
|
||||||
|
}
|
||||||
|
if p != ip {
|
||||||
|
panic("p != ip")
|
||||||
|
}
|
||||||
|
if p != jp {
|
||||||
|
panic("p != jp")
|
||||||
|
}
|
||||||
|
if pp != ipp {
|
||||||
|
panic("pp != ipp")
|
||||||
|
}
|
||||||
|
// pp does not implement J.
|
||||||
|
|
||||||
// Test that non-interface types can be used as ...interface{} arguments.
|
// Test that non-interface types can be used as ...interface{} arguments.
|
||||||
if got := second(z, p, pp, u16, u32, u64, u128, f32, f64, c128, s, b, m, c); got != ip {
|
if got := second(z, p, pp, u16, u32, u64, u128, f32, f64, c128, s, b, m, c); got != ip {
|
Loading…
Reference in New Issue
Block a user