I need an advice for setting an interface{} value

Hello i have a Tag struct which has data type, value and bytes fields. I am setting the value and bytes of value with SetValue and SetBytes fuctions. When i set the value i also set bytes and vice versa.

If there is a better or idiomatic way, please advice.

Here is the code:

//data types
const (
	Bit     uint8 = 1
	Uint8   uint8 = 2
	Int8    uint8 = 3
	//...
)

type Tag struct {
	//...
	DataType     uint8
	bytes        []byte
	value        interface{}
}

func (t *Tag) SetBytes(bytesOfValue []byte) error {
	//try to set value
	var value interface{}
	b := bytes.NewReader(bytesOfValue)
	var err error
	switch t.DataType {
	case Bit:
		var v bool
		err = binary.Read(b, binary.BigEndian, &v)
		value = v
	case Uint8:
		var v uint8
		err = binary.Read(b, binary.BigEndian, &v)
		value = v
	case Int8:
		var v int8
		err = binary.Read(b, binary.BigEndian, &v)
		value = v
		//...
	}
	if err != nil {
		fmt.Println(err.Error())
		return errors.New("reading bytes failed")
	}
	t.value = value
	//set bytes
	t.bytes = bytesOfValue
	return nil
}

func (t *Tag) SetValue(value interface{}) error {
	//try to set bytes
	var v interface{}
	var ok bool
	switch t.DataType {
	case Bit:
		v, ok = value.(bool)
	case Uint8:
		v, ok = value.(uint8)
	case Int8:
		v, ok = value.(int8)
	//...
	}
	if !ok {
		return errors.New("value is not valid")
	}
	b := new(bytes.Buffer)
	err := binary.Write(b, binary.BigEndian, v)
	if err != nil {
		return errors.New("writing bytes failed")
	}
	t.bytes = b.Bytes()
	//set value
	t.value = value
	return nil
}

And i set the value and bytes of value like this:

//create tag
t := Tag{
	DataType: Int8,
}

//set value
err := t.SetValue(int8(-128))
if err != nil {
	fmt.Println(err.Error())
	return
}
fmt.Println(t.GetBytes(), t.GetValue())

//set bytes
err = t.SetBytes([]byte{128})
if err != nil {
	fmt.Println(err.Error())
	return
}
fmt.Println(t.GetBytes(), t.GetValue())

Here is the playground link: https://play.golang.org/p/hHpTIw9Fxx5

Best regards

Test your code.

//set value
t := Tag{}
fmt.Println(t)
t.SetValue(int8(-128))
fmt.Println(t)

{0 [] <nil>}
{0 [] <nil>}

Please assign a DataType for t. I didnā€™t share the full code. There is a NewTag function which creates tags.
I also edited the post.

Effective Go

itā€™s helpful to arrange when designing your data structures that the zero value of each type can be used without further initialization. This means a user of the data structure can create one and get right to work.

Where is the NewTag function?


//tag struct
type Tag struct {
	DataType uint8
	bytes    []byte
	value    interface{}
}

Why is Tag.DataType exported?

These questions are irrevelant.

Did you ever use binary packageā€™s Read and Write function?

Do you have an advice on the subject or just wasting time?

In golang. Field name starting with an upper case letter to be accessible from other package

1 Like

Are you kidding?

If you donā€™t have an idea about the subject, you donā€™t have to write!

Sorry to have bothered you, I had not read the first postā€¦

You need to improve your code. You also need to improve the performance of your code.

The Tag data structure is large and inefficient. Redesign the Tag structure and reduce the size by more than 50%.

The algorithms are inefficient. Reduce the CPU time for SetValue by 90% or more. Reduce the CPU time for SetBytes by 80% or more. Reduce the allocations for SetValue to zero. Reduce the allocations for SetBytes to one.

Ad hominem (Latin for ā€˜to the personā€™), typically refers to a rhetorical strategy where the speaker attacks the character, motive, or some other attribute of the person making an argument rather than attacking the substance of the argument itself.

1 Like

You misunderstood my question.

I know why Go exports identifiers.

The Go Programming Language Specification

Exported identifiers

An identifier may be exported to permit access to it from another package. An identifier is exported if both:

  1. the first character of the identifierā€™s name is a Unicode upper case letter (Unicode class ā€œLuā€); and
  2. the identifier is declared in the package block or it is a field name or method name.

All other identifiers are not exported.

I wanted to know why the designer of the type Tag struct chose to export the Tag.DataType field. Do you know? Is it a good design?

thanks for your time and answer petrus.

my question was about repeating binary.Read function since it is not accepting interface{} value.

i proceed with development and tests. since this is a low level device communication protocol i canā€™t explain all design criterias with modern aproach and i donā€™t want to to take your time, iā€™ll consider your advices.

best regards

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.