// config/config.go
package config
import (
"github.com/spf13/viper"
)
type Config struct {
Database DatabaseConfig `mapstructure:"database"`
Server ServerConfig `mapstructure:"server"`
Redis RedisConfig `mapstructure:"redis"`
Jwt JwtConfig `mapstructure:"jwt"`
Smtp SmtpConfig `mapstructure:"smtp"`
}
func New() (config *Config) {
viper.AddConfigPath(".")
viper.SetConfigName("config")
if err := viper.ReadInConfig(); err != nil {
panic(err)
}
if err := viper.Unmarshal(&config); err != nil {
panic(err)
}
return
}
// db/connection.go
package db
import (
"fmt"
"my.project/config"
"gorm.io/driver/mysql"
"gorm.io/gorm"
)
func New(config config.DatabaseConfig) *gorm.DB {
dsn := fmt.Sprintf(
"%s:%s@tcp(%s:%d)/%s?charset=utf8mb4&parseTime=True&loc=Local",
config.Username, config.Password, config.Host, config.Port, config.Database,
)
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
if err != nil {
fmt.Println("Failed to connect to database")
panic(err)
}
RunMigrations(db)
return db
}
// main.go
package main
import (
"fmt"
"my.project/config"
)
func main() {
config := config.New()
fmt.Println(config.Database)
db := db.New(config.Database)
if db == nil {
panic("Failed to connect to database")
}
}
In the above snippets, config
is a pointer to a Config type variable (apparently from the return type of config.New()
), but config.Database
seems to be a value (not a reference).
I assumed config.Database
would be a reference either but it's not (I tried to print out them, config
was definitely a reference and config.Database
was a value).
Can anyone help me to understand why? Thank you in advance!
It turned out that this was originated from one of the language design decisions. In fact, if you use (*config).Database
, it is absolutely valid. However, the makers of Go deemed this notation cumbersome, so the language permits us to write config.Database
,
without an explicit dereference. These pointers to structs even have their own name struct pointers
and they are automatically dereferenced. Here's another superb explanation for "auto-deferencing": When do Go's pointers dereference themselves