unknwon/the-way-to-go_ZH_CN · error

key not found

Error message

key not found

What it means

Returned by URLStore.Get in the chapter 19 URL-shortener after the RPC-style refactor: Get(key, url *string) takes a read lock (s.mu.RLock with defer RUnlock), and when the map lookup s.urls[*key] misses it returns errors.New("key not found"). The Redirect HTTP handler prints the error's string form — effectively the 404 cause for an unknown short key.

Source

Thrown at eBook/19.8.md:40

```

要使 `URLStore` 成为 RPC 服务,需要修改 `Put()` 和 `Get()` 方法使它们符合上述函数签名。以下是修改后的签名:
```go
func (s *URLStore) Get(key, url *string) error
func (s *URLStore) Put(url, key *string) error
```

`Get()` 代码变更为:

```go
func (s *URLStore) Get(key, url *string) error {
	s.mu.RLock()
	defer s.mu.RUnlock()
	if u, ok := s.urls[*key]; ok {
		*url = u
		return nil
	}
	return errors.New("key not found")
}
```

现在,键和长 URL 都变成了指针,必须加上前缀 `*` 来取得它们的值,例如 `*key` 这种形式。`u` 是一个值,可以用 `*url = u` 来将其赋值给指针。

接着对 `Put()` 代码做同样的改动:
```go
func (s *URLStore) Put(url, key *string) error {
	for {
		*key = genKey(s.Count())
			if err := s.Set(key, url); err == nil {
			break
		}
	}
	if s.save != nil {
		s.save <- record{*key, *url}
	}
	return nil

View on GitHub (pinned to 7a54d34d36)

Solutions

  1. On startup, always run load() to replay the persisted store before serving traffic, so previously issued keys stop missing
  2. In Redirect, treat this error as 404: if err := store.Get(&key, &url); err != nil { http.NotFound(w, req); return } — or redirect to the homepage per the book's variant
  3. Promote the string to a sentinel (var ErrKeyNotFound = errors.New("key not found")) and branch with errors.Is so refactors keep the 404 mapping working
  4. If keys vanish under load, verify Get's RLock/RUnlock pairing and that Put still writes records through save <- record{*key, *url}

Example fix

// before
err := store.Get(&key, &url)
if err != nil {
	fmt.Println("Error:", err) // raw 'key not found' leaked to stdout
}

// after
var url string
if err := store.Get(&key, &url); err != nil {
	http.Error(w, "no such key: "+key, http.StatusNotFound)
	return
}
http.Redirect(w, req, url, http.StatusFound)
Defensive patterns

Strategy: fallback

Try / catch

var url string
if err := store.Get(&key, &url); err != nil {
	// unknown short key: degrade gracefully
	http.NotFound(w, req) // or redirect to the homepage
	return
}
http.Redirect(w, req, url, http.StatusFound)

Prevention

When it happens

Trigger: The Redirect handler receives /somekey that was never Put: the key is absent from s.urls. Also key-format mismatches (keys come from genKey(s.Count()) and are short strings), keys lost because the service restarted without load() replaying the persisted store, or typo'd/garbled short URLs.

Common situations: Persistence bugs: the save channel dropped records, data_store.txt was not loaded on startup, or Count() desynchronized after load causing genKey to emit colliding keys; hand-typed keys with case errors; multi-instance deployments where only one replica holds the key.

Related errors


AI-assisted analysis of unknwon/the-way-to-go_ZH_CN@7a54d34d36 (2026-08-15). Data as JSON: /api/errors/0fb86f7ddaeec2f6. Report an issue: GitHub.