Skip to content

reflect: methods are sorted #30688

Closed
Closed
@bep

Description

@bep

What version of Go are you using (go version)?

$ go version
go version go1.12 darwin/amd64

Does this issue reproduce with the latest release?

Yes.

What operating system and processor architecture are you using (go env)?

go env Output
$ go env
GOARCH="amd64"
GOBIN=""
GOCACHE="/Users/bep/Library/Caches/go-build"
GOEXE=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="darwin"
GOOS="darwin"
GOPATH="/Users/bep/go"
GOPROXY=""
GORACE=""
GOROOT="/usr/local/go"
GOTMPDIR=""
GOTOOLDIR="/usr/local/go/pkg/tool/darwin_amd64"
GCCGO="gccgo"
CC="clang"
CXX="clang++"
CGO_ENABLED="1"
GOMOD=""
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -m64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -fdebug-prefix-map=/var/folders/n6/s_85mm8d31j6yctssnmn_g1r0000gn/T/go-build199582095=/tmp/go-build -gno-record-gcc-switches -fno-common"

What did you do?

https://play.golang.org/p/c91WyY2NI2l

package main

import (
	"fmt"
	"reflect"
)

type I interface {
	Method2()
	Method3()
	Method1()
}

type T struct {
	Field2 string
	Field3 string
	Field1 string
}

func main() {
	fmt.Println("Methods:")
	t := reflect.TypeOf((*I)(nil)).Elem()
	for i := 0; i < t.NumMethod(); i++ {
		fmt.Println(i, ":", t.Method(i).Name)
	}

	fmt.Println("Fields:")
	t = reflect.TypeOf(T{})
	for i := 0; i < t.NumField(); i++ {
		fmt.Println(i, ":", t.Field(i).Name)
	}
}

What did you expect to see?

Order preserved for both fields and methods.

What did you see instead?

Sorted order for methods, preserved for fields:

Methods:
0 : Method1
1 : Method2
2 : Method3
Fields:
0 : Field2
1 : Field3
2 : Field1

I was writing a generator to marshal some interfaces to JSON. I suspect Go's JSON package uses reflection behind the scenes, and that the order is preserved because of the "fields only" restriction. This breaks once you try to add methods to the mix.

The documentation in both of the cases above is similar:

Method returns a function value corresponding to v's i'th method.

Metadata

Metadata

Assignees

No one assigned

    Labels

    DocumentationIssues describing a change to documentation.FrozenDueToAgeNeedsFixThe path to resolution is known, but the work has not been done.help wanted

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions