Question
# Suppose we define a user structure object User in the code, which has the following properties .
type User struct { ID string // 必需项 Name string // 必需项 Age int // 非必需项 Gender bool // 非必需项 }
When initializing the object, the simplest way is to directly fill in the attribute value, such as
u := &User{ID: "12glkui234d", Name: "菜刀", Age: 18, Gender: true}
But there is a problem here: User object The attributes in are not necessarily exportable. For example, User has an attribute field called password (the first letter is lowercase, not exported). If a User object needs to be constructed in other modules, the password field cannot be filled.
So we need to define a function to construct the User object. The simplest constructor method that can be thought of is as follows.
func NewUser(id, name string, age int, gender bool) *User { return &User{ ID: id, Name: name, Age: age, Gender: gender, } }
But there are also some problems: for the User object, only the ID and Name properties are required, Age and Gender are non-required, and default values cannot be set. For example, the default value of Age is 0, and the default value of Gender is false, which is obviously unreasonable.
Faced with this problem, what are the solutions we can adopt?
Option 1: Multi-function construction
The crudest solution we can think of is: set up a constructor for each parameter situation . As shown in the following code
func NewUser(id, name string) *User { return &User{ID: id, Name: name} } func NewUserWithAge(id, name string, age int) *User { return &User{ID: id, Name: name, Age: age} } func NewUserWithGender(id, name string, gender bool) *User { return &User{ID: id, Name: name, Gender: gender} } func NewUserWithAgeGender(id, name string, age int, gender bool) *User { return &User{ID: id, Name: name, Age: age, Gender: gender} }
这种方式适合参数较少且不易发生变化的情况。该方式在 Go 标准库中也有使用,例如 net 包中的 Dial 和 DialTimeout 方法。
func Dial(network, address string) (Conn, error) {} func DialTimeout(network, address string, timeout time.Duration) (Conn, error) {}
但该方式的缺陷也很明显:试想,如果构造对象 User 增加了参数字段 Phone,那么我们需要新增多少个组合函数?
方案二:配置化
另外一种常见的方式是配置化,我们将所有可选的参数放入一个 Config 的配置结构体中。
type User struct { ID string Name string Cfg *Config } type Config struct { Age int Gender bool } func NewUser(id, name string, cfg *Config) *User { return &User{ID: id, Name: name, Cfg: cfg} }
这样,我们只需要一个 NewUser() 函数,不管之后增加多少配置选项,NewUser 函数都不会得到破坏。
但是,这种方式,我们需要先构造 Config 对象,这时候对 Config 的构造又回到了方案一中存在的问题。
方案三:函数式选项模式
面对这样的问题,我们还可以选择函数式选项模式。
首先,我们定义一个 Option 函数类型
type Option func(*User)
然后,为每个属性值定义一个返回 Option 函数的函数
func WithAge(age int) Option { return func(u *User) { u.Age = age } } func WithGender(gender bool) Option { return func(u *User) { u.Gender = gender } }
此时,我们将 User 对象的构造函数改为如下所示
func NewUser(id, name string, options ...Option) *User { u := &User{ID: id, Name: name} for _, option := range options { option(u) } return u }
按照这种构造方式,我们就可以这样配置 User 对象了
u := NewUser("12glkui234d", "菜刀", WithAge(18), WithGender(true))
以后不管 User 增加任何参数 XXX,我们只需要增加对应的 WithXXX 函数即可,是不是非常地优雅?
Functional Options 这种编程模式,我们经常能在各种项目中找到它的身影。例如,我在 tidb 项目中仅使用 opts ... 关键字搜索,就能看到这么多使用了 Functional Options 的代码(截图还未包括全部)。
Summary
The functional option pattern solves the problem of how to dynamically and flexibly configure parameters for objects, but it needs to be used in appropriate scenarios.
When the configuration parameters of the object are complex, such as many optional parameters, non-imported fields, parameters may increase with the version, etc., then the functional option mode can help very well. us.
The above is the detailed content of A programming model active in many Go projects. For more information, please follow other related articles on the PHP Chinese website!

go语言有缩进。在go语言中,缩进直接使用gofmt工具格式化即可(gofmt使用tab进行缩进);gofmt工具会以标准样式的缩进和垂直对齐方式对源代码进行格式化,甚至必要情况下注释也会重新格式化。

闭包(closure)是一个函数以及其捆绑的周边环境状态(lexical environment,词法环境)的引用的组合。 换而言之,闭包让开发者可以从内部函数访问外部函数的作用域。 闭包会随着函数的创建而被同时创建。

本篇文章带大家了解一下golang 的几种常用的基本数据类型,如整型,浮点型,字符,字符串,布尔型等,并介绍了一些常用的类型转换操作。

go语言叫go的原因:想表达这门语言的运行速度、开发速度、学习速度(develop)都像gopher一样快。gopher是一种生活在加拿大的小动物,go的吉祥物就是这个小动物,它的中文名叫做囊地鼠,它们最大的特点就是挖洞速度特别快,当然可能不止是挖洞啦。

是,TiDB采用go语言编写。TiDB是一个分布式NewSQL数据库;它支持水平弹性扩展、ACID事务、标准SQL、MySQL语法和MySQL协议,具有数据强一致的高可用特性。TiDB架构中的PD储存了集群的元信息,如key在哪个TiKV节点;PD还负责集群的负载均衡以及数据分片等。PD通过内嵌etcd来支持数据分布和容错;PD采用go语言编写。

在写 Go 的过程中经常对比这两种语言的特性,踩了不少坑,也发现了不少有意思的地方,下面本篇就来聊聊 Go 自带的 HttpClient 的超时机制,希望对大家有所帮助。


Hot AI Tools

Undresser.AI Undress
AI-powered app for creating realistic nude photos

AI Clothes Remover
Online AI tool for removing clothes from photos.

Undress AI Tool
Undress images for free

Clothoff.io
AI clothes remover

AI Hentai Generator
Generate AI Hentai for free.

Hot Article

Hot Tools

MinGW - Minimalist GNU for Windows
This project is in the process of being migrated to osdn.net/projects/mingw, you can continue to follow us there. MinGW: A native Windows port of the GNU Compiler Collection (GCC), freely distributable import libraries and header files for building native Windows applications; includes extensions to the MSVC runtime to support C99 functionality. All MinGW software can run on 64-bit Windows platforms.

DVWA
Damn Vulnerable Web App (DVWA) is a PHP/MySQL web application that is very vulnerable. Its main goals are to be an aid for security professionals to test their skills and tools in a legal environment, to help web developers better understand the process of securing web applications, and to help teachers/students teach/learn in a classroom environment Web application security. The goal of DVWA is to practice some of the most common web vulnerabilities through a simple and straightforward interface, with varying degrees of difficulty. Please note that this software

Atom editor mac version download
The most popular open source editor

VSCode Windows 64-bit Download
A free and powerful IDE editor launched by Microsoft

Dreamweaver CS6
Visual web development tools
