How can i get a struct size?

7,546 views
Skip to first unread message

18126...@163.com

unread,
May 13, 2016, 12:11:38 AM5/13/16
to golang-nuts
 my code like below, use binary.Size to get my struct size ,but it returns -1, not my required size. is there anybody help me ?
type Req struct{
       header Head
       body Body
}
type Head struct{
       length uint32
       sequence uint32
}
type Body struct{
       entitySize uint32
       entity []Entity
}
type Entity struct{
       id uint32
       status uint16
}

func main() {
e1 := Entity{}
e2 := Entity{}
v := Req{}
v.body.entity = append(v.body.entity, e1)
v.body.entity = append(v.body.entity, e2)
fmt.Println(binary.Size(v))
// this output is -1.
}


Dave Cheney

unread,
May 13, 2016, 12:23:20 AM5/13/16
to golang-nuts, 18126...@163.com
encoding/binary.Size can only report the encoded size under very strict circumstances. You probably want something like unsafe.Sizeof

https://golang.org/pkg/unsafe/#Sizeof

andrey mirtchovski

unread,
May 13, 2016, 12:23:31 AM5/13/16
to 18126...@163.com, golang-nuts
as per the documentation, binary.Size works only on things which are
"a fixed-size value or a slice of fixed-size values, or a pointer to
such data". you have a struct there, called "Body", which is not fixed
size as it contains a slice. you wouldn't have a problem calling
binary.Size on an []Entity, but not on a Body:

https://play.golang.org/p/k37YLbnRje
> --
> You received this message because you are subscribed to the Google Groups
> "golang-nuts" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to golang-nuts...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.

Roberto Zanotto

unread,
May 13, 2016, 12:25:27 AM5/13/16
to golang-nuts, 18126...@163.com
reflect.TypeOf(Req{}).Size()

18126...@163.com

unread,
May 13, 2016, 2:25:11 AM5/13/16
to golang-nuts, 18126...@163.com
I try "unsafe.Sizeof(Req{})" and "reflect.TypeOf(Req{}).Size" to calculate the 'Req' struct size by byte , they all return 24, if i append the 3rd Entity,  it's still 24.  

It's not the result i want 30, i think it should be increase 6 bytes with every increased Entity. 

I 'am a newer in go program , i expect to get a most convenient way to calculate the Req struct size by byte, can anybody give me some ideas , many thanks.




在 2016年5月13日星期五 UTC+8下午12:11:38,18126...@163.com写道:

Michael Jones

unread,
May 13, 2016, 2:52:29 AM5/13/16
to 18126...@163.com, golang-nuts
The structure member entity (“entity []Entity”) is a slice, that is, it is a handle describing the location and size of a array of Entities. The size of the handle is not increased as the array size increases.

The kind of size you are thinking of is “how many bytes in the Body structure and how many active bytes in the particular backing array referenced by the entity member/” This is a fine question to ask, but it is not the answer to the question “how many bytes in the Body structure?”

You seem to want:  SIZE(Body) + len(someParticularBody.entity)*SIZE(Entity)

— 
Michael Jones, CEO  •  mic...@wearality.com  •  +1 650 656-6989 
Wearality Corporation  •  289 S. San Antonio Road  •  Los Altos, CA 94022

18126...@163.com

unread,
May 13, 2016, 3:27:35 AM5/13/16
to golang-nuts, 18126...@163.com
The following code is working, but it seems not very flexiable, it must know the slice position in whole body, then call len(silce) and sizeof(Entiy)


// this function is from modified binary size() function
func sizeof(t reflect.Type) int {
       switch t.Kind() {
       case reflect.Array:
              fmt.Println("reflect.Array")
              if s := sizeof(t.Elem()); s >= 0 {
                     return s * t.Len()
              }

       case reflect.Struct:
              fmt.Println("reflect.Struct")
              sum := 0
              for i, n := 0, t.NumField(); i < n; i++ {
                     s := sizeof(t.Field(i).Type)
                     if s < 0 {
                            return -1
                     }
                     sum += s
              }
              return sum

       case reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64,
              reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
              reflect.Float32, reflect.Float64, reflect.Complex64, reflect.Complex128:
              fmt.Println("reflect.int")
              return int(t.Size())
       case reflect.Slice:
                     //modified place
              fmt.Println("reflect.Slice:", sizeof(t.Elem()))
              return 0
       }

       return -1

}

type Req struct{
       header Head
       body Body
}
type Head struct{
       length uint32
       sequence uint32
}
type Body struct{
       entitySize uint32
       entity []Entity
}
type Entity struct{
       id uint32
       status uint16
}

func main() {
       e1 := Entity{}
       e2 := Entity{}
       e3 := Entity{}

       v := Req{}
       v.body.entity = append(v.body.entity, e1)
       v.body.entity = append(v.body.entity, e2)
       v.body.entity = append(v.body.entity, e3)

       base := sizeof(reflect.TypeOf(v))
       variable := len(v.body.entity ) * sizeof(reflect.TypeOf(e3))
       fmt.Println(base + variable)
}




在 2016年5月13日星期五 UTC+8下午2:52:29,Michael Jones写道:
Message has been deleted

Dave Cheney

unread,
May 13, 2016, 4:29:22 AM5/13/16
to golang-nuts
Can I ask a different question. If you could compute the size of Req, what would you do with that information?

刘翰林

unread,
May 13, 2016, 6:34:04 AM5/13/16
to Dave Cheney, golang-nuts
I get the length of the body ,translate it to bytes, then use socket to send bytes . Do that,I don't need to count when I translate uint32 to bytes .

发自我的 iPhone

> 在 2016年5月13日,16:29,Dave Cheney <da...@cheney.net> 写道:
>
> Can I ask a different question. If you could compute the size of Req, what would you do with that information?
>
> --
> You received this message because you are subscribed to a topic in the Google Groups "golang-nuts" group.
> To unsubscribe from this topic, visit https://groups.google.com/d/topic/golang-nuts/Bq4c-1nvmCw/unsubscribe.
> To unsubscribe from this group and all its topics, send an email to golang-nuts...@googlegroups.com.

刘翰林

unread,
May 13, 2016, 6:35:31 AM5/13/16
to Roberto Zanotto, golang-nuts
The reflect.Type.Size() can't calculate slice struct.

发自我的 iPhone

在 2016年5月13日,15:43,Roberto Zanotto <roby...@gmail.com> 写道:

Why don't you just use reflect.Type.Size()? Do you need to chase the pointer in the slice headers recursively?

--
You received this message because you are subscribed to a topic in the Google Groups "golang-nuts" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/golang-nuts/Bq4c-1nvmCw/unsubscribe.
To unsubscribe from this group and all its topics, send an email to golang-nuts...@googlegroups.com.

Ian Lance Taylor

unread,
May 13, 2016, 9:32:50 AM5/13/16
to 刘翰林, Dave Cheney, golang-nuts
On Fri, May 13, 2016 at 3:32 AM, 刘翰林 <18126...@163.com> wrote:
> I get the length of the body ,translate it to bytes, then use socket to send bytes . Do that,I don't need to count when I translate uint32 to bytes .

Assuming you want to translate to bytes using encoding/binary, decode
the value into bytes, then ask for the length of what you got.

Is there a reason you want to get the length first?

Ian


>> 在 2016年5月13日,16:29,Dave Cheney <da...@cheney.net> 写道:
>>
>> Can I ask a different question. If you could compute the size of Req, what would you do with that information?
>>
>> --
>> You received this message because you are subscribed to a topic in the Google Groups "golang-nuts" group.
>> To unsubscribe from this topic, visit https://groups.google.com/d/topic/golang-nuts/Bq4c-1nvmCw/unsubscribe.
>> To unsubscribe from this group and all its topics, send an email to golang-nuts...@googlegroups.com.
>> For more options, visit https://groups.google.com/d/optout.
>
> --
> You received this message because you are subscribed to the Google Groups "golang-nuts" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts...@googlegroups.com.

Konstantin Khomoutov

unread,
May 13, 2016, 9:53:56 AM5/13/16
to Ian Lance Taylor, 刘翰林, Dave Cheney, golang-nuts
On Fri, 13 May 2016 06:32:34 -0700
Ian Lance Taylor <ia...@golang.org> wrote:

> On Fri, May 13, 2016 at 3:32 AM, 刘翰林 <18126...@163.com> wrote:
> > I get the length of the body ,translate it to bytes, then use
> > socket to send bytes . Do that,I don't need to count when I
> > translate uint32 to bytes .
>
> Assuming you want to translate to bytes using encoding/binary, decode
> the value into bytes, then ask for the length of what you got.
>
> Is there a reason you want to get the length first?

Supposedly to not buffer the serialized data.

刘翰林

unread,
May 13, 2016, 11:18:49 AM5/13/16
to Konstantin Khomoutov, Ian Lance Taylor, Dave Cheney, golang-nuts
When I get the head,the total bytes length can be used for body bytes read on the peer socket. Or is there another way?

发自我的 iPhone

Roberto Zanotto

unread,
May 13, 2016, 11:48:57 AM5/13/16
to golang-nuts, flat...@users.sourceforge.net, ia...@golang.org, da...@cheney.net, 18126...@163.com
If you can, use something like gob

It's a binary encoding and it takes care of all those things for you.

刘翰林

unread,
May 13, 2016, 7:29:37 PM5/13/16
to Roberto Zanotto, golang-nuts, flat...@users.sourceforge.net, ia...@golang.org, da...@cheney.net
Thanks for your advice,I will try it:)


Reply all
Reply to author
Forward
0 new messages