如何区分 int null 和默认为零的 int,以及实际上等于零的 int?

huangapple go评论160阅读模式
英文:

How to differentiate int null and defaulted to zero from int actually equal to zero?

问题

我是一位长期使用Python的用户,现在转向使用Go,但我仍然有一些问题需要重新掌握基本的类型和指针管理技巧。

我有一个程序从RabbitMq接收事件(但无论我们讨论的是哪种传输方式,问题都是一样的)。其中一个事件包含一个可选字段F1,类型为int。

我的理解是,如果事件中没有该字段,Go会将其默认设置为0。但是0是该字段的有效值,我需要区分值为0和值未定义的情况。

我考虑将字段定义为*int,以便实际上将其值设置为"nil"。但是当我接收到一个事件时,F1会被设置为实际指向的值,还是发送方的值地址?
我还有其他选择吗?

英文:

I am a long time python user moving to Go, and I still have some issues to reacquire basic skill to manage typing and pointer.

I have a program receiving event from RabbitMq (But the problem would be the same no matter what transport we are talking about). One of the even contain an optional field F1 typed as int.

My understanding is, if the field is not present in the event, then go will default it to 0. But 0 is a valid value for that field, and I need to differentiate cases where the value is 0, and cases where the value is non defined.

I thought to make my field a *int to actually have "nil" as a value. But then when when a receive an event, will F1 be set to the actual pointed value, or the value address from the sender?
Do I have any other alternative?

答案1

得分: 5

在大多数情况下,使用指向值的指针是有意义的。例如:

type RabbitMessage struct {
    F1 *int `json:"f1"`
}

这将根据在将数据发送到RabbitMQ之前如何序列化数据的方式来确定其工作的确切细节。如果你使用的是JSON,那么这应该没有问题,因为在Go中,空值和省略值都将表示为nil。当提供值时,它将被设置为您期望的值(它不会使用发送方的地址)。

英文:

In most cases, using a pointer to the value makes sense. E.g

type RabbitMessage struct {
    F1 *int `json:"f1"`
}

The exact details of how this will work depends on how you serialise your data before sending it over RabbitMQ. If you are using JSON, then there should be no issue with this as both a null value, and an omitted value, will be represented in Go as nil. When the value is provided, it will be set to the value you expect (it will not use the address from the sender).

答案2

得分: 0

如果你只控制接收程序,那么据我所知,你无法区分由Go自动初始化为0的int和由发送方设置为0的int。

不过,如果你可以修改发送程序,另一种方法是在int旁边添加一个布尔字段,表示该int是否已设置。然后在接收端,你可以检查布尔值是否为true。

你也可以发送一个指向int的指针:

type Message struct {
    Value *int `json:"value"`
}

message := Message{Value: &4}

不过要注意,当解组时,你将得到一个int指针,你需要解引用它。

英文:

If you control only the receiver program, then AFAICT you can not differentiate between an int that has been automatically initialized to 0 by go from an int that has been set to 0 by the sender.

If you can modify the sender program though, an alternative could be to add a boolean field along with your int, telling whether the int is set or not. Then on the receiving end you can check whether the boolean is true or not.

You can also send a pointer to an int:

type Message struct {
    Value *int `json:"value"`
}

message := Message{Value: 4}

Be aware though that when unmarshalling this you'll get an int pointer you'll need to dereference.

答案3

得分: 0

“我还有其他选择吗?” - 是的,你可以定义一个自定义类型,类似于 sql.NullInt64

type OptionalInt struct {
	Int     int
	IsValid bool
}

func NewOptionalInt(i int) OptionalInt {
	return OptionalInt{Int: i, IsValid: true}
}

func (o *OptionalInt) UnmarshalJSON(data []byte) error {
	if string(data) != "null" {
		if err := json.Unmarshal(data, &o.Int); err != nil {
			return err
		}
		o.IsValid = true
	}
	return nil
}

func (o OptionalInt) MarshalJSON() ([]byte, error) {
	if o.IsValid {
		return json.Marshal(o.Int)
	}
	return json.Marshal(nil)
}
英文:

"Do I have any other alternative?" -- Yes, you can define a custom type, similar to sql.NullInt64.

type OptionalInt struct {
	Int     int
	IsValid bool
}

func NewOptionalInt(i int) OptionalInt {
	return OptionalInt{Int: i, IsValid: true}
}

func (o *OptionalInt) UnmarshalJSON(data []byte) error {
	if string(data) != "null" {
		if err := json.Unmarshal(data, &o.Int); err != nil {
			return err
		}
		o.IsValid = true
	}
	return nil
}

func (o OptionalInt) MarshalJSON() ([]byte, error) {
	if o.IsValid {
		return json.Marshal(o.Int)
	}
	return json.Marshal(nil)
}

huangapple
  • 本文由 发表于 2021年8月16日 17:26:18
  • 转载请务必保留本文链接:https://go.coder-hub.com/68800319.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定