第一个线上项目不足,应该学习的地方
ent的批量创建
names := []string{"pedro", "xabi", "layla"}
bulk := make([]*ent.PetCreate, len(names))
for i, name := range names {
bulk[i]=client.Pet.Create().SetName(name).SetOwner(a8m)
}
pets, err := client.Pet.CreateBulk(bulk...).Save(ctx)
判断切片中是否包含某元素
func ConvertStrSlice2Map(sl []string) map[string]struct{} {
set := make(map[string]struct{}, len(sl))
for _, v := range sl {
set[v] = struct{}{}
}
return set
}
func InStrMap(m map[string]struct{}, s string) bool {
_, ok := m[s]
return ok
}
func StrIfContain(str []string, s string) bool {
mp := ConvertStrSlice2Map(str)
return InStrMap(mp, s)
}
相似结构体的转换
package main
import (
"fmt"
"github.com/jinzhu/copier"
)
type User struct {
Name string
Age int
}
type Employee struct {
Name string
Age int
Role string
}
func main() {
user := User{Name: "dj", Age: 18}
employee := Employee{}
copier.Copy(&employee, &user)
fmt.Printf("%#v\n", employee)
}
将user对象中的字段赋值到employee的同名字段中。如果目标对象中没有同名的字段,则该字段被忽略。
关于map
对于var定义的map不宜直接赋值,最好使用:=方式初始化,以免出现空指针错误
关于config.yaml
在同时要使用两个yaml时,通过wire依赖注入传入,在provideset中直接接收即可,wire会帮助自动生成代码,eg:
main.go
package main
import (
"flag"
"os"
"github.com/go-kratos/beer-shop/app/catalog/service/internal/conf"
"github.com/go-kratos/kratos/v2"
"github.com/go-kratos/kratos/v2/config"
"github.com/go-kratos/kratos/v2/config/file"
"github.com/go-kratos/kratos/v2/log"
"github.com/go-kratos/kratos/v2/registry"
"github.com/go-kratos/kratos/v2/transport/grpc"
"go.opentelemetry.io/otel/exporters/jaeger"
"go.opentelemetry.io/otel/sdk/resource"
tracesdk "go.opentelemetry.io/otel/sdk/trace"
semconv "go.opentelemetry.io/otel/semconv/v1.4.0"
)
// go build -ldflags "-X main.Version=x.y.z"
var (
// Name is the name of the compiled software.
Name = "beer.catalog.service"
// Version is the version of the compiled software.
Version string
// flagconf is the config flag.
flagconf string
)
func init() {
flag.StringVar(&flagconf, "conf", "../../configs", "config path, eg: -conf config.yaml")
}
func newApp(logger log.Logger, gs *grpc.Server, rr registry.Registrar) *kratos.App {
return kratos.New(
kratos.Name(Name),
kratos.Version(Version),
kratos.Metadata(map[string]string{}),
kratos.Logger(logger),
kratos.Server(
gs,
),
kratos.Registrar(rr),
)
}
func main() {
flag.Parse()
logger := log.With(
log.NewStdLogger(os.Stdout),
"service.name", Name,
"service.version", Version,
"ts", log.DefaultTimestamp,
"caller", log.DefaultCaller,
)
c := config.New(
config.WithSource(
file.NewSource(flagconf),
),
)
if err := c.Load(); err != nil {
panic(err)
}
var bc conf.Bootstrap
if err := c.Scan(&bc); err != nil {
panic(err)
}
var rc conf.Registry
if err := c.Scan(&rc); err != nil {
panic(err)
}
exp, err := jaeger.New(jaeger.WithCollectorEndpoint(jaeger.WithEndpoint(bc.Trace.Endpoint)))
if err != nil {
panic(err)
}
tp := tracesdk.NewTracerProvider(
tracesdk.WithBatcher(exp),
tracesdk.WithResource(resource.NewSchemaless(
semconv.ServiceNameKey.String(Name),
)),
)
app, cleanup, err := initApp(bc.Server, &rc, bc.Data, logger, tp)
if err != nil {
panic(err)
}
defer cleanup()
// start and wait for stop signal
if err := app.Run(); err != nil {
panic(err)
}
}
wire.go
// +build wireinject
// The build tag makes sure the stub is not built in the final build.
package main
import (
"github.com/go-kratos/beer-shop/app/catalog/service/internal/biz"
"github.com/go-kratos/beer-shop/app/catalog/service/internal/conf"
"github.com/go-kratos/beer-shop/app/catalog/service/internal/data"
"github.com/go-kratos/beer-shop/app/catalog/service/internal/server"
"github.com/go-kratos/beer-shop/app/catalog/service/internal/service"
"github.com/go-kratos/kratos/v2"
"github.com/go-kratos/kratos/v2/log"
"github.com/google/wire"
tracesdk "go.opentelemetry.io/otel/sdk/trace"
)
// initApp init kratos application.
func initApp(*conf.Server, *conf.Registry, *conf.Data, log.Logger, *tracesdk.TracerProvider) (*kratos.App, func(), error) {
panic(wire.Build(server.ProviderSet, data.ProviderSet, biz.ProviderSet, service.ProviderSet, newApp))
}
server.go
package server
import (
"github.com/go-kratos/beer-shop/app/catalog/service/internal/conf"
"github.com/go-kratos/kratos/v2/registry"
"github.com/google/wire"
consul "github.com/go-kratos/kratos/contrib/registry/consul/v2"
consulAPI "github.com/hashicorp/consul/api"
)
// ProviderSet is server providers.
var ProviderSet = wire.NewSet(NewGRPCServer, NewRegistrar)
func NewRegistrar(conf *conf.Registry) registry.Registrar {
c := consulAPI.DefaultConfig()
c.Address = conf.Consul.Address
c.Scheme = conf.Consul.Scheme
cli, err := consulAPI.NewClient(c)
if err != nil {
panic(err)
}
r := consul.New(cli, consul.WithHealthCheck(false))
return r
}