Golang标准包装结构

I am faily new to Go and I am trying to create a structured application using guidance from Ben Johnson's webpage. Unfortunately, his example is not a complete working application.

His webpage is https://medium.com/@benbjohnson/standard-package-layout-7cdbc8391fc1

I have tried to use his methods and I keep getting "Undefined: db" error. It doesn't tell me what line is causing the error, just the file "MSSQL.go"

Could someone help with guidance to help me fix this error?

Edited code with accepted solution.

StatementPrinter.go

    package statementprinter

    type Statement struct {
      CustomerId   string
      CustomerName string
    }

    type StatementService interface {
      Statement(id string) (*Statement, error)
    }

main.go

            package main

            import (
              "fmt"
              "log"
              "github.com/ybenjolin/StatementPrinter"
              "github.com/ybenjolin/StatementPrinter/mssql"
              "database/sql"
              _ "github.com/alexbrainman/odbc"
            )

            const DB_INFO = "Driver={SQL Server};Server=cdc-edb2;Database=CostarReports;Trusted_Connection=yes;"

            var db *sql.DB

            func init() {
              var err error
              db, err = sql.Open("odbc", DB_INFO)
              if err != nil {
                log.Fatal("Error opening database connection.
", err.Error())
              }
              err = db.Ping()
              if err != nil {
                log.Fatal("Error pinging database server.
", err.Error())
              }
              fmt.Println("Database connection established.")
            }

            func main () {
              var err error
              defer db.Close()

              // Create services
              // Changes required here. Was ss := &statementprinter.Stat..
              ss := &mssql.StatementService{DB: db}

              // Use service
              var s *statementprinter.Statement
              s, err = ss.Statement("101583")
              if err != nil {
                log.Fatal("Query failed:", err.Error())
              }
              fmt.Printf("Statement: %+v
", s)
            }

mssql.go

    package mssql  

    import (
      _ "github.com/alexbrainman/odbc"
      "database/sql"
      "github.com/ybenjolin/StatementPrinter"
    )

    // StatementService represents a MSSQL implementation of statemenetprinter.StatementService.
    type StatementService struct {
      DB *sql.DB
    }

    // Statement returns a statement for a given customer.
    func (s *StatementService) Statement(customer string) (*statementprinter.Statement, error) {
      var err error
      var t statementprinter.Statement
      // Changes required here. Was row := db.Query......
      row := s.DB.QueryRow(`Select Customer, CustomerName From AccountsReceivable.rptfARStatementHeader(?)`, customer)
      if row.Scan(&t.CustomerId, &t.CustomerName); err != nil {
        return nil, err
      }
      return &t, nil

This seems like it's just a typo. It seems like the problematic line is in the method

 func (s *StatementService) Statement(customer string) 

in mssql.go,

  row := db.QueryRow(`Select Customer, CustomerName From AccountsReceivable.rptfARStatementHeader(?)`, customer)

QueryRow is supposed to be a method of db, but db is not defined. However, in the struct

type StatementService struct {
  DB *sql.DB
}

there's a *sql.DB instance. The method you're using has a *StatementService parameter, s. So, my guess is the intention would be to access the sql.DB field in s like so

func (s *StatementService) Statement(customer string) (*statementprinter.Statement, error) {
  var err error
  var t statementprinter.Statement
   //CHANGED LINE:
  row := s.DB.QueryRow(`Select Customer, CustomerName From AccountsReceivable.rptfARStatementHeader(?)`, customer)
  if row.Scan(&t.CustomerId, &t.CustomerName); err != nil {
    return nil, err
  }
  return &t, nil

Then, the method is called in main.go, and is passed a StatementService instance that contains a database:

ss := &statementprinter.StatementService{DB: db}

I believe you need to change this line to

ss := &mssql.StatementService{DB: db}

becuase that's the actual interface implementation. The line you have now treats the StatementService interface like a struct which will not compile. The global db in main.go lives for the lifetime of the application. It's just a pointer which is copied around for use.