go-useragent
go-useragent is a high-performance zero-allocation Go library designed to parse browser name and version, operating system, and device type information from user-agent strings with sub-microsecond parsing times.
It achieves this efficiency by using a modified hybrid trie data structure to store and rapidly look up user-agent tokens. It utilizes heuristic rules, tokenizing a list of user-agent strings into a trie during startup. During runtime, the parsing process involves a straightforward lookup operation.
This project is actively maintained and used by the lightweight website analytics project Medama.
Installation
go get -u github.com/medama-io/go-useragent
Usage
This type of parser is typically initialized once at application startup and reused throughout the application's lifecycle. While it doesn't offer the exhaustive coverage of traditional regex-based parsers, it can be paired with one to handle unknown edge cases, where the trie-based parser acts as a fast path for the majority of user-agents.
Example
package main import ( "fmt" "github.com/medama-io/go-useragent" ) func main() { // Create a new parser. Initialize only once during application startup. ua := useragent.NewParser() // Example user-agent string. str := "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36" // Parse the user-agent string. agent := ua.Parse(str) // Access parsed information using agent fields. fmt.Println(agent.Browser()) // agents.BrowserChrome fmt.Println(agent.BrowserVersion()) // 118.0.0.0 fmt.Println(agent.OS()) // agents.OSWindows fmt.Println(agent.Device()) // agents.DeviceDesktop // Boolean helper functions. fmt.Println(agent.IsChrome()) // true fmt.Println(agent.IsFirefox()) // false fmt.Println(agent.IsWindows()) // true fmt.Println(agent.IsLinux()) // false fmt.Println(agent.IsDesktop()) // true fmt.Println(agent.IsTV()) // false fmt.Println(agent.IsBot()) // false // and many more... // Version helper functions. fmt.Println(agent.BrowserVersionMajor()) // 118 fmt.Println(agent.BrowserVersionMinor()) // 0 fmt.Println(agent.BrowserVersionPatch()) // 0.0 }
Refer to the pkg.go.dev documentation for more details on available fields and their meanings.
Benchmarks
Benchmarks were performed against ua-parser/uap-go and mileusena/useragent on an Apple M3 Pro Processor.
mise run bench MedamaParserGetSingle-12 3871813 287.2 ns/op 0 B/op 0 allocs/op MileusnaParserGetSingle-12 1322602 945.1 ns/op 600 B/op 16 allocs/op UAPParserGetSingle-12 986428 1112 ns/op 233 B/op 8 allocs/op MedamaParserGetAll-12 75219 14616 ns/op 0 B/op 0 allocs/op MileusnaParserGetAll-12 25644 46806 ns/op 28878 B/op 732 allocs/op UAPParserGetAll-12 19263 54621 ns/op 10316 B/op 352 allocs/op
Acknowledgements
- The library draws inspiration from the techniques outlined in this Raygun blog post.