构造函数的实现

  之所以叫构造函数而不叫构造方法,是因为它确实只是一个普通函数,它不属于任何结构体(也不能属于某个结构体,否则就和它的“构造”功能相悖了),它的功能通常是返回一个结构体变量指针(不返回结构体变量是因为指针不会发生值拷贝效率更高)。
 
  实现构造函数常见形式有两种:T.New()和NewT(),两种形式并没有孰优孰劣,即便是在Go标准库里也没有统一,如:rand.New()、aes.NewCipher()、time.NewTicker()。第三方包也是各种形式都有,如:memcache.New()、redis.NewClient()、hashids.NewData()。用哪种方式主要是看个人喜好和团队规范,选择其中一种并全项目统一使用即可。
 
  一般来说建议使用T.New()形式,由于函数名都是New(),所以每个构造函数都必须单独使用一个包,从而避免 'New' redeclared in this package 问题,这样就可以通过T1.New()、T2.New()、T3.New()这种写法执行构造操作。




 
  先来演示使用T.New()形式实现构造函数:

package ArticleModel

import "fmt"

// ArticleModel ArticleModel结构体
type ArticleModel struct {
   aid   int64  // 文章ID号
   title string // 文章标题
   click int64  // 点击次数
}

// New ArticleModel构造函数
func New(aid int64, title string, click int64) (articleModel *ArticleModel) {
   articleModel = new(ArticleModel)

   (*articleModel).aid = aid
   (*articleModel).title = title
   (*articleModel).click = click

   return
}

// Print ArticleModel的Print()方法
func (articleModel *ArticleModel) Print() {
   aid := (*articleModel).aid
   title := (*articleModel).title
   click := (*articleModel).click
   fmt.Printf("第%d篇 => %s [点击数:%d]\n", aid, title, click)
}

package main

import ArticleModel "go-src/demo"

func main() {
   // 调用构造函数获取ArticleModel对象
   articleModel := ArticleModel.New(9527, "PHP是世界上最好の语言", 1024)

   // 调用ArticleModel对象的Print()方法
   articleModel.Print() // 第9527篇 => PHP是世界上最好の语言 [点击数:1024]
}





  接下来演示使用NewT()形式实现构造函数:

package ArticleModel

import "fmt"

// ArticleModel ArticleModel结构体
type ArticleModel struct {
   aid   int64  // 文章ID号
   title string // 文章标题
   click int64  // 点击次数
}

// NewArticleModel ArticleModel构造函数
func NewArticleModel(aid int64, title string, click int64) (articleModel *ArticleModel) {
   articleModel = new(ArticleModel)

   (*articleModel).aid = aid
   (*articleModel).title = title
   (*articleModel).click = click

   return
}

// Print ArticleModel的Print()方法
func (articleModel *ArticleModel) Print() {
   aid := (*articleModel).aid
   title := (*articleModel).title
   click := (*articleModel).click
   fmt.Printf("第%d篇 => %s [点击数:%d]\n", aid, title, click)
}

package main

import ArticleModel "go-src/demo"

func main() {
   // 调用构造函数获取ArticleModel对象
   articleModel := ArticleModel.NewArticleModel(9527, "PHP是世界上最好の语言", 1024)

   // 调用ArticleModel对象的Print()方法
   articleModel.Print()
}





  由于Go不支持重载,所以无法像Java一样实现定义多个构造函数,但是Go也可以变相实现重载构造函数,而且构造函数的形参为可变参数(没有个数和顺序的限制),如下面的代码:

package ArticleModel

import "fmt"

// ArticleModel ArticleModel结构体
type ArticleModel struct {
   aid   int64  // 文章ID号
   title string // 文章标题
   click int64  // 点击次数
}

// New ArticleModel构造函数
func New(funcSlice ...func(articleModel *ArticleModel)) (articleModel *ArticleModel) {
   articleModel = new(ArticleModel)

   for _, function := range funcSlice {
      function(articleModel)
   }

   return articleModel
}

// WithAid 设置aid字段
func WithAid(aid int64) func(articleModel *ArticleModel) {
   return func(articleModel *ArticleModel) {
      (*articleModel).aid = aid
   }
}

// WithTitle 设置title字段
func WithTitle(title string) func(articleModel *ArticleModel) {
   return func(articleModel *ArticleModel) {
      (*articleModel).title = title
   }
}

// WithClick 设置click字段
func WithClick(click int64) func(articleModel *ArticleModel) {
   return func(articleModel *ArticleModel) {
      (*articleModel).click = click
   }
}

// Print ArticleModel的Print()方法
func (articleModel *ArticleModel) Print() {
   aid := (*articleModel).aid
   title := (*articleModel).title
   click := (*articleModel).click
   fmt.Printf("第%d篇 => %s [点击数:%d]\n", aid, title, click)
}

package main

import "go-src/model/ArticleModel"

func main() {
   // 创建ArticleModel对象(1个参数)
   articleModel1 := ArticleModel.New(
      ArticleModel.WithAid(9527),
   )
   articleModel1.Print() // 第9527篇 =>  [点击数:0]

   // 创建ArticleModel对象(2个参数)
   articleModel2 := ArticleModel.New(
      ArticleModel.WithAid(9527),
      ArticleModel.WithTitle("PHP是世界上最好の语言"),
   )
   articleModel2.Print() // 第9527篇 => PHP是世界上最好の语言 [点击数:0]

   // 创建ArticleModel对象(3个参数)
   articleModel3 := ArticleModel.New(
      ArticleModel.WithAid(9527),
      ArticleModel.WithTitle("PHP是世界上最好の语言"),
      ArticleModel.WithClick(1024),
   )
   articleModel3.Print() // 第9527篇 => PHP是世界上最好の语言 [点击数:1024]
}

Copyright © 2024 码农人生. All Rights Reserved