在SPA中创建对象时,如何防止重复的ID? 还是应该留在数据库?

I have a react app that fetches data from golang api which queries data from postgres database. One of my models is deeply nested JSON so I used JSONB datatype in postgres.

CREATE table rules (
    id serial primary key,
    rule jsonb
);

In golang, I have the structure

type Rule struct {
    ID int `json:"id"`
    Name string `json:"name"`
    ...succeeding fields are deeply nested data
}

And in the SPA I have the model

interface Rule {
    id number
    name string
    ....same as from the golang api model
}

To create a new Rule object in the SPA, I assign 0 to id. The newly created rule is sent to golang rest api. Then in the api, I first ask the postgres database for the next value for the serial id (using POSTGRES nextval), assign that acquired id into the Rule struct ID field,

nextValidId := <result of nextval>
rule.ID = nextValidId

JSON marshal the rule object then insert to db

ruleBytes, _ := json.Marshal(rule)
INSERT INTO rules_table VALUES (<nextValidId>, <ruleBytes>);

This way I avoided duplicate ids which may happen if an SPA is handling the Id generation. However, I find my method somewhat complicated already. I know I can generate ids from SPA too but how do I avoid duplicated ids without using the method I used above? or am I overthinking things?

Update1: I also thought about adding another Rule struct in golang without the ID field so that I don't have to use nextval just to put the id inside the JSON, but is it a good programming design to have multiple models for inserting and retrieving from db and another model for response to the SPA?

Let the database generate the new id since that's exactly SERIAL types are for in PostgreSQL.

In golang, you can insert a new record and retrieve the generated id by using sql.DB.QueryRow(...) and .Scan() using an insert statement with a RETURNING clause, e.g.:

var newId int
query := "INSERT INTO rules (rule) VALUES ($1) RETURNING id"
err := db.QueryRow(query, newRule).Scan(&newId)
// TODO: check err
log.Printf("newId=%d", newId)