Пакет userip
Пакет userip предоставляет функции для извлечения IP-адреса пользователя из запроса и связывает его с Context. Context предоставляет сопоставление значений ключа, где ключи и значения являются типом interface{}
. Типы ключей должны поддерживать равенство, а значения должны быть безопасными для одновременного использования несколькими горутинами. Пакеты, такие как userip, скрывают подробности этого сопоставления и предоставляют строго типизированный доступ к определенному значению Context.
Чтобы избежать конфликтов ключей, userip определяет неэкспортируемый тип key и использует значение этого типа в качестве ключа контекста:
// Тип key не экспортируемый для предотвращения конфликтов
// с контекстными ключами, определенными в других пакетах.
type key int
// userIPkey - это контекстный ключ для IP-адреса пользователя.
// Его значение равно нулю.
// Если в этом пакете определены другие контекстные ключи,
// у них будут разные значения целого числа.
const userIPKey key = 0
FromRequest извлекает значение userIP из http.Request:
func FromRequest(req *http.Request) (net.IP, error) {
ip, _, err := net.SplitHostPort(req.RemoteAddr)
if err != nil {
return nil, fmt.Errorf("userip: %q is not IP:port", req.RemoteAddr)
}
NewContext возвращает новый Context, который содержит предоставленное значение userIP:
func NewContext(ctx context.Context, userIP net.IP) context.Context {
return context.WithValue(ctx, userIPKey, userIP)
}
FromContext извлекает userIP из Context:
func FromContext(ctx context.Context) (net.IP, bool) {
// ctx.Value возвращает nil, если ctx не имеет значения для ключа;
// net.IP возвращает ok = false для nil.
userIP, ok := ctx.Value(userIPKey).(net.IP)
return userIP, ok
}