{"record":{"id":"67feca4de822b0e0","repo":"geektutu/7days-golang","slug":"rpc-service-already-defined-67feca","errorCode":null,"errorMessage":"rpc: service already defined: ","messagePattern":"rpc: service already defined: ","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"gee-rpc/day5-http-debug/server.go","lineNumber":223,"sourceCode":"\t\t}\n\t\tgo server.ServeConn(conn)\n\t}\n}\n\n// Accept accepts connections on the listener and serves requests\n// for each incoming connection.\nfunc Accept(lis net.Listener) { DefaultServer.Accept(lis) }\n\n// Register publishes in the server the set of methods of the\n// receiver value that satisfy the following conditions:\n//\t- exported method of exported type\n//\t- two arguments, both of exported type\n//\t- the second argument is a pointer\n//\t- one return value, of type error\nfunc (server *Server) Register(rcvr interface{}) error {\n\ts := newService(rcvr)\n\tif _, dup := server.serviceMap.LoadOrStore(s.name, s); dup {\n\t\treturn errors.New(\"rpc: service already defined: \" + s.name)\n\t}\n\treturn nil\n}\n\n// Register publishes the receiver's methods in the DefaultServer.\nfunc Register(rcvr interface{}) error { return DefaultServer.Register(rcvr) }\n\nconst (\n\tconnected        = \"200 Connected to Gee RPC\"\n\tdefaultRPCPath   = \"/_geeprc_\"\n\tdefaultDebugPath = \"/debug/geerpc\"\n)\n\n// ServeHTTP implements an http.Handler that answers RPC requests.\nfunc (server *Server) ServeHTTP(w http.ResponseWriter, req *http.Request) {\n\tif req.Method != \"CONNECT\" {\n\t\tw.Header().Set(\"Content-Type\", \"text/plain; charset=utf-8\")\n\t\tw.WriteHeader(http.StatusMethodNotAllowed)","sourceCodeStart":205,"sourceCodeEnd":241,"githubUrl":"https://github.com/geektutu/7days-golang/blob/cf3644382101dc13e7fd92e8f5c66cabc51bcd3b/gee-rpc/day5-http-debug/server.go#L205-L241","documentation":"Register calls LoadOrStore on the server's serviceMap; if a service with the same derived name is already present, it returns this duplicate-registration error instead of overwriting the existing service. This protects against accidentally replacing method tables.","triggerScenarios":"Calling Register(new(Foo)) twice on the same Server, or registering two receivers whose type names are identical (e.g. two structs both named Foo in different packages).","commonSituations":"Test suites re-registering fixtures in setup code without a fresh Server, accidentally registering the same receiver on both DefaultServer and a custom Server reused across tests, or name collisions between same-named types.","solutions":["Ensure Register is called only once per service per Server instance (guard with sync.Once or init)","Use a distinct exported type name for each service so the derived names don't collide","Create a fresh Server for each test case instead of reusing one, or ignore the duplicate error intentionally if re-registration is expected"],"exampleFix":"// before\nsrv.Register(new(Foo))\nsrv.Register(new(Foo)) // duplicate\n// after\nvar once sync.Once\nfunc registerFoo(s *geeprc.Server) {\n    once.Do(func() { s.Register(new(Foo)) })\n}","handlingStrategy":"try-catch","validationCode":"type Registrable interface{ ServiceName() string }\nfunc alreadyRegistered(server *geeprc.Server, name string) bool {\n    seen, _ := registeredNames.Load(name) // track names in a sync.Map of your own\n    return seen != nil\n}","typeGuard":null,"tryCatchPattern":"if err := srv.Register(new(Foo)); err != nil {\n    if strings.Contains(err.Error(), \"service already defined\") {\n        log.Printf(\"Foo already registered; skipping\")\n    } else {\n        return err\n    }\n}","preventionTips":["Register each service exactly once, e.g. in an init() or a sync.Once-guarded setup","Give every RPC receiver a unique exported type name to avoid derived-name collisions","In tests, build a fresh Server per test instead of reusing a global DefaultServer","Centralize registration in one function so duplicates are easy to spot in review"],"tags":["rpc","registration","duplicate"],"backgroundTag":"rpc-service-already-defined","analyzedSha":"cf3644382101dc13e7fd92e8f5c66cabc51bcd3b","analyzedAt":"2026-09-03T18:31:24.087Z","contentChangedAt":"2026-09-03T18:31:24.087Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}