How to implement common functions of encapsulated models in golang?

PHPz
Release: 2024-02-11 23:42:09
forward
1065 people have browsed it

How to implement common functions of encapsulated models in golang?

In Golang, common functions of encapsulated models can be implemented by using structures and methods. A structure is a custom data type that can be used to encapsulate related data and methods. Methods are functions associated with a structure, and the members of the structure can be accessed and manipulated within the method. By defining functions as structures, we can associate functions with specific structures to implement common operations in encapsulated models. In Golang, we can use receivers to specify the structure to which the method belongs. The receiver can be a value type or a pointer type, choose the appropriate receiver type according to your needs. By defining the structure method, we can implement common operations in the encapsulated model, such as getting or setting field values, performing specific operations, etc. In this way, we can access and operate the encapsulated data by calling the structure's methods, achieving more flexible and reusable code.

Question content

I have 2 packages as models:

category:

package class

import (
    "encoding/json"
    "student_management/model/base"
)

type classes struct {
    classes []class
}

type class struct {
    id                int `json:"student_id"`
    name              int `json:"name"`
    homeroomteacherid int `json:"homeroom_teacher_id"`
}

func readdata() (chan class, int) {
    var classes classes
    bytevalue := base.readjson("db/student_class.json")
    json.unmarshal(bytevalue, &classes)

    classchannel := make(chan class)
    go func () {
        for i := 0; i < len(classes.classes); i++ {
            classchannel <- classes.classes[i]
        }
        close(classchannel)
    }()

    return classchannel, len(classes.classes)
}
Copy after login

teacher:

package teacher

import (
    "encoding/json"
    base "student_management/model/base"
)

type teachers struct {
    teachers []teacher `json:"teachers"`
}

type teacher struct {
    base.persions
    homeroomteacher bool `json:"homeroom_teacher"`
}

func readdata() (chan teacher, int) {
    var teachers teachers
    bytevalue := base.readjson("db/teachers.json")
    json.unmarshal(bytevalue, &teachers)

    teacherchannel := make(chan teacher)
    go func () {
        for i := 0; i < len(teachers.teachers); i++ {
            teacherchannel <- teachers.teachers[i]
        }
        close(teacherchannel)
    }()

    return teacherchannel, len(teachers.teachers)
}
Copy after login

So you can see that the readdata function is executed repeatedly. Now I can call data from the channel using class.readdata() and teacher.readdata().

How to write a readdata() function for use by two packages?

I tried creating a base package that uses generics like this:

package base

func ReadData[Models any, Model any](fileName string, m Models) (chan interface{}, int) {
    byteValue := ReadJSON(fileName)
    json.Unmarshal(byteValue, &m)

    channel := make(chan Model)
    go func () {
        for i := 0; i < len(m.Models); i++ {
            channel <- m.Models[i]
        }
        close(channel)
    }()

    return channel, len(models.Models)
}
Copy after login

But cannot find m.models, I mean teachers.teachers or classes.classescannot be used

Please tell me what to do in this case

Solution

Use generics (introduced in go 1.18). Create a readdata() function with parameter types representing the values ​​to be decoded from json and passed on the channel.

Note: You should check for errors and report errors (including errors from base.readjson()).

func readdata[t any](filename, fieldname string) (chan t, int, error) {
    var m map[string][]t
    bytevalue := base.readjson(filename)
    if err := json.unmarshal(bytevalue, &wrapper); err != nil {
        return nil, 0, err
    }

    values := m[fieldname]

    valueschannel := make(chan t)
    go func() {
        for _, v := range values {
            valueschannel <- v
        }
        close(valueschannel)
    }()

    return valueschannel, len(values), nil
}
Copy after login

Call example:

ch, n, err := readdata[class.class]("db/student_class.json", "classes")

// or

ch, n, err := readdata[teacher.teacher]("db/teachers.json", "teachers")
Copy after login

Please note that returning the number of read values ​​should be redundant. Since you closed the returned channel correctly, the caller can use for range on the returned channel and the channel will correctly receive all values ​​sent on it and then terminate.

Also note that since all values ​​are ready (decoded) when returning to the channel, this concurrency is redundant and only reduces efficiency. You have a slice of decoded values, just return it and let the caller choose how it wants to handle it (concurrent or non-concurrent).

So your readdata() should look like this:

func readdata[t any](filename, fieldname string) ([]t, error) {
    var m map[string][]t
    bytevalue := base.readjson(filename)
    if err := json.unmarshal(bytevalue, &wrapper); err != nil {
        return nil, err
    }

    return m[fieldname]
}
Copy after login

Also note that if the input json object has only one field, there is no need to pass fieldname, you can get the value from the decoded m map like this:

func readdata[t any](filename string) ([]t, error) {
    var m map[string][]t
    bytevalue := base.readjson(filename)
    if err := json.unmarshal(bytevalue, &wrapper); err != nil {
        return nil, err
    }

    for _, v := range m {
        return v, nil
    }

    return nil, errors.new("empty json")
}
Copy after login

Then calling it is simple:

classes, err := ReadData[class.Class]("db/student_class.json")

// or

teachers, err := ReadData[teacher.Teacher]("db/teachers.json")
Copy after login

The above is the detailed content of How to implement common functions of encapsulated models in golang?. For more information, please follow other related articles on the PHP Chinese website!

source:stackoverflow.com
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template
About us Disclaimer Sitemap
php.cn:Public welfare online PHP training,Help PHP learners grow quickly!