Path parsing for segment unmarshaling and slicing.

Overview

parth

go get github.com/codemodus/parth/v2

Package parth provides path parsing for segment unmarshaling and slicing. In other words, parth provides simple and flexible access to (URL) path parameters.

Along with string, all basic non-alias types are supported. An interface is available for implementation by user-defined types. When handling an int, uint, or float of any size, the first valid value within the specified segment will be used.

Usage

Variables
func Segment(path string, i int, v interface{}) error
func Sequent(path, key string, v interface{}) error
func Span(path string, i, j int) (string, error)
func SubSeg(path, key string, i int, v interface{}) error
func SubSpan(path, key string, i, j int) (string, error)
type Parth
    func New(path string) *Parth
    func NewBySpan(path string, i, j int) *Parth
    func NewBySubSpan(path, key string, i, j int) *Parth
    func (p *Parth) Err() error
    func (p *Parth) Segment(i int, v interface{})
    func (p *Parth) Sequent(key string, v interface{})
    func (p *Parth) Span(i, j int) string
    func (p *Parth) SubSeg(key string, i int, v interface{})
    func (p *Parth) SubSpan(key string, i, j int) string
type Unmarshaler

Setup ("By Index")

import (
    "fmt"

    "github.com/codemodus/parth/v2"
)

func handler(w http.ResponseWriter, r *http.Request) {
    var s string
    if err := parth.Segment(r.URL.Path, 4, &s); err != nil {
        fmt.Fprintln(os.Stderr, err)
    }

    fmt.Println(r.URL.Path)
    fmt.Printf("%v (%T)\n", s, s)

    // Output:
    // /some/path/things/42/others/3
    // others (string)
}

Setup ("By Key")

import (
    "fmt"

    "github.com/codemodus/parth/v2"
)

func handler(w http.ResponseWriter, r *http.Request) {
    var i int64
    if err := parth.Sequent(r.URL.Path, "things", &i); err != nil {
        fmt.Fprintln(os.Stderr, err)
    }

    fmt.Println(r.URL.Path)
    fmt.Printf("%v (%T)\n", i, i)

    // Output:
    // /some/path/things/42/others/3
    // 42 (int64)
}

Setup (Parth Type)

import (
    "fmt"

    "github.com/codemodus/parth/v2"
)

func handler(w http.ResponseWriter, r *http.Request) {
    var s string
    var f float32

    p := parth.New(r.URL.Path)
    p.Segment(2, &s)
    p.SubSeg("key", 1, &f)
    if err := p.Err(); err != nil {
        fmt.Fprintln(os.Stderr, err)
    }

    fmt.Println(r.URL.Path)
    fmt.Printf("%v (%T)\n", s, s)
    fmt.Printf("%v (%T)\n", f, f)

    // Output:
    // /zero/one/two/key/four/5.5/six
    // two (string)
    // 5.5 (float32)
}

Setup (Unmarshaler)

import (
    "fmt"

    "github.com/codemodus/parth/v2"
)

func handler(w http.ResponseWriter, r *http.Request) {
    /*
        type mytype []byte

        func (m *mytype) UnmarshalSegment(seg string) error {
            *m = []byte(seg)
        }
    */

    var m mytype
    if err := parth.Segment(r.URL.Path, 4, &m); err != nil {
        fmt.Fprintln(os.Stderr, err)
    }

    fmt.Println(r.URL.Path)
    fmt.Printf("%v == %q (%T)\n", m, m, m)

    // Output:
    // /zero/one/two/key/four/5.5/six
    // [102 111 117 114] == "four" (mypkg.mytype)
}

More Info

Keep Using http.HandlerFunc And Minimize context.Context Usage

The most obvious use case for parth is when working with any URL path such as the one found at http.Request.URL.Path. parth is fast enough that it can be used multiple times in place of a single use of similar router-parameter schemes or even context.Context. There is no need to use an alternate http handler function definition in order to pass data that is already being passed. The http.Request type already holds URL data and parth is great at handling it. Additionally, parth takes care of parsing selected path segments into the types actually needed. Parth not only does more, it's usually faster and less intrusive than the alternatives.

Indexes

If an index is negative, the negative count begins with the last segment. Providing a 0 for the second index is a special case which acts as an alias for the end of the path. An error is returned if: 1. Any index is out of range of the path; 2. When there are two indexes, the first index does not precede the second index.

Keys

If a key is involved, functions will only handle the portion of the path subsequent to the provided key. An error is returned if the key cannot be found in the path.

First Whole, First Decimal (Restated - Important!)

When handling an int, uint, or float of any size, the first valid value within the specified segment will be used.

Documentation

View the GoDoc

Benchmarks

Go 1.11
benchmark                             iter       time/iter   bytes alloc        allocs
---------                             ----       ---------   -----------        ------
BenchmarkSegmentString-8          30000000     39.60 ns/op        0 B/op   0 allocs/op
BenchmarkSegmentInt-8             20000000     65.60 ns/op        0 B/op   0 allocs/op
BenchmarkSegmentIntNegIndex-8     20000000     86.60 ns/op        0 B/op   0 allocs/op
BenchmarkSpan-8                  100000000     18.20 ns/op        0 B/op   0 allocs/op
BenchmarkStdlibSegmentString-8     5000000    454.00 ns/op       50 B/op   2 allocs/op
BenchmarkStdlibSegmentInt-8        3000000    526.00 ns/op       50 B/op   2 allocs/op
BenchmarkStdlibSpan-8              3000000    518.00 ns/op       69 B/op   2 allocs/op
BenchmarkContextLookupSetGet-8     1000000   1984.00 ns/op      480 B/op   6 allocs/op
Issues
  • Why parth/v2 in go.mod?

    Why parth/v2 in go.mod?

    You is generating conflicts when depending on the package in non-go mod way (Go < 1.11).

    Can you make the path consistent to the actual Github path? https://github.com/codemodus/parth

    Thanks!

    opened by h2non 2
  • Use type switch to reduce the count of exposed functions.

    Use type switch to reduce the count of exposed functions.

    func SegmentToBool(path string, i int) (bool, error)
    func SegmentToFloat32(path string, i int) (float32, error)
    func SegmentToFloat64(path string, i int) (float64, error)
    func SegmentToInt(path string, i int) (int, error)
    func SegmentToInt16(path string, i int) (int16, error)
    func SegmentToInt32(path string, i int) (int32, error)
    func SegmentToInt64(path string, i int) (int64, error)
    func SegmentToInt8(path string, i int) (int8, error)
    func SegmentToString(path string, i int) (string, error)
    func SegmentToUint(path string, i int) (uint, error)
    func SegmentToUint16(path string, i int) (uint16, error)
    func SegmentToUint32(path string, i int) (uint32, error)
    func SegmentToUint64(path string, i int) (uint64, error)
    func SegmentToUint8(path string, i int) (uint8, error)
    func SpanToString(path string, firstSeg, lastSeg int) (string, error)
    func SubSegToBool(path, key string) (bool, error)
    func SubSegToFloat32(path, key string) (float32, error)
    func SubSegToFloat64(path, key string) (float64, error)
    func SubSegToInt(path, key string) (int, error)
    func SubSegToInt16(path, key string) (int16, error)
    func SubSegToInt32(path, key string) (int32, error)
    func SubSegToInt64(path, key string) (int64, error)
    func SubSegToInt8(path, key string) (int8, error)
    func SubSegToString(path, key string) (string, error)
    func SubSegToUint(path, key string) (uint, error)
    func SubSegToUint16(path, key string) (uint16, error)
    func SubSegToUint32(path, key string) (uint32, error)
    func SubSegToUint64(path, key string) (uint64, error)
    func SubSegToUint8(path, key string) (uint8, error)
    func SubSpanToString(path, key string, lastSeg int) (string, error)
    type Parth
        func New(path string) *Parth
        func NewFromSpan(path string, firstSeg, lastSeg int) *Parth
        func NewFromSubSpan(path, key string, lastSeg int) *Parth
        func (p *Parth) Err() error
        func (p *Parth) SegmentToBool(i int) bool
        func (p *Parth) SegmentToFloat32(i int) float32
        func (p *Parth) SegmentToFloat64(i int) float64
        func (p *Parth) SegmentToInt(i int) int
        func (p *Parth) SegmentToInt16(i int) int16
        func (p *Parth) SegmentToInt32(i int) int32
        func (p *Parth) SegmentToInt64(i int) int64
        func (p *Parth) SegmentToInt8(i int) int8
        func (p *Parth) SegmentToString(i int) string
        func (p *Parth) SegmentToUint(i int) uint
        func (p *Parth) SegmentToUint16(i int) uint16
        func (p *Parth) SegmentToUint32(i int) uint32
        func (p *Parth) SegmentToUint64(i int) uint64
        func (p *Parth) SegmentToUint8(i int) uint8
        func (p *Parth) SpanToString(firstSeg, lastSeg int) string
        func (p *Parth) SubSegToBool(key string) bool
        func (p *Parth) SubSegToFloat32(key string) float32
        func (p *Parth) SubSegToFloat64(key string) float64
        func (p *Parth) SubSegToInt(key string) int
        func (p *Parth) SubSegToInt16(key string) int16
        func (p *Parth) SubSegToInt32(key string) int32
        func (p *Parth) SubSegToInt64(key string) int64
        func (p *Parth) SubSegToInt8(key string) int8
        func (p *Parth) SubSegToString(key string) string
        func (p *Parth) SubSegToUint(key string) uint
        func (p *Parth) SubSegToUint16(key string) uint16
        func (p *Parth) SubSegToUint32(key string) uint32
        func (p *Parth) SubSegToUint64(key string) uint64
        func (p *Parth) SubSegToUint8(key string) uint8
        func (p *Parth) SubSpanToString(key string, lastSeg int) string
    

    should instead be

    func Segment(path string, i int, v interface{}) error
    func Span(path string, firstSeg, lastSeg int) (string, error)
    func SubSeg(path, key string, v interface{}) error
    func SubSpan(path, key string, lastSeg int) (string, error)
    type Parth
        func New(path string) *Parth
        func NewFromSpan(path string, firstSeg, lastSeg int) *Parth
        func NewFromSubSpan(path, key string, lastSeg int) *Parth
        func (p *Parth) Err() error
        func (p *Parth) Segment(i int, v interface{})
        func (p *Parth) Span(firstSeg, lastSeg int) string
        func (p *Parth) SubSeg(key string, v interface{})
        func (p *Parth) SubSpan(key string, lastSeg int) string
    
    opened by daved 1
Owner
Code Modus
Code Modus
A declarative struct-tag-based HTML unmarshaling or scraping package for Go built on top of the goquery library

goq Example import ( "log" "net/http" "astuart.co/goq" ) // Structured representation for github file name table type example struct { Title str

Andrew Stuart 217 May 30, 2022
Match regex group into go struct using struct tags and automatic parsing

regroup Simple library to match regex expression named groups into go struct using struct tags and automatic parsing Installing go get github.com/oris

Ori Seri 111 Jun 24, 2022
Decode / encode XML to/from map[string]interface{} (or JSON); extract values with dot-notation paths and wildcards. Replaces x2j and j2x packages.

mxj - to/from maps, XML and JSON Decode/encode XML to/from map[string]interface{} (or JSON) values, and extract/modify values from maps by key or key-

Charles Banning 520 Jun 19, 2022
Pagser is a simple, extensible, configurable parse and deserialize html page to struct based on goquery and struct tags for golang crawler

Pagser Pagser inspired by page parser。 Pagser is a simple, extensible, configurable parse and deserialize html page to struct based on goquery and str

foolin 62 Jun 13, 2022
[Go] Package of validators and sanitizers for strings, numerics, slices and structs

govalidator A package of validators and sanitizers for strings, structs and collections. Based on validator.js. Installation Make sure that Go is inst

Alex Saskevich 5.4k Jun 22, 2022
Take screenshots of websites and create PDF from HTML pages using chromium and docker

gochro is a small docker image with chromium installed and a golang based webserver to interact wit it. It can be used to take screenshots of w

Christian Mehlmauer 48 Jun 12, 2022
Parse data and test fixtures from markdown files, and patch them programmatically, too.

go-testmark Do you need test fixtures and example data for your project, in a language agnostic way? Do you want it to be easy to combine with documen

Eric Myhre 17 Jun 17, 2022
Watches container registries for new and changed tags and creates an RSS feed for detected changes.

Tagwatch Watches container registries for new and changed tags and creates an RSS feed for detected changes. Configuration Tagwatch is configured thro

Wolfgang Popp 1 Jan 7, 2022
A general purpose application and library for aligning text.

align A general purpose application that aligns text The focus of this application is to provide a fast, efficient, and useful tool for aligning text.

John Moore 75 Mar 24, 2022
Parse placeholder and wildcard text commands

allot allot is a small Golang library to match and parse commands with pre-defined strings. For example use allot to define a list of commands your CL

Sebastian Müller 55 Apr 13, 2022
:evergreen_tree: Parses indented code and returns a tree structure.

codetree Parses indented code (Python, Pug, Stylus, Pixy, codetree, etc.) and returns a tree structure. Installation go get github.com/aerogo/codetree

Aero 20 Mar 6, 2022
Elegant Scraper and Crawler Framework for Golang

Colly Lightning Fast and Elegant Scraping Framework for Gophers Colly provides a clean interface to write any kind of crawler/scraper/spider. With Col

Colly 16.9k Jun 30, 2022
Encoding and decoding for fixed-width formatted data

fixedwidth Package fixedwidth provides encoding and decoding for fixed-width formatted Data. go get github.com/ianlopshire/go-fixedwidth Usage Struct

Ian Lopshire 63 May 8, 2022
A Go library to parse and format vCard

go-vcard A Go library to parse and format vCard. Usage f, err := os.Open("cards.vcf") if err != nil { log.Fatal(err) } defer f.Close() dec := vcard.

Simon Ser 72 Jun 29, 2022
Zero-width character detection and removal for Go

go-zero-width Zero-width character detection and removal for Go. Inspired by this Medium article. Installation go get github.com/trubitsyn/go-zero-wid

Nikola Trubitsyn 103 Jun 8, 2022
Parse RSS, Atom and JSON feeds in Go

gofeed The gofeed library is a robust feed parser that supports parsing both RSS, Atom and JSON feeds. The library provides a universal gofeed.Parser

null 1.9k Jun 28, 2022
Takes a full name and splits it into individual name parts

gonameparts gonameparts splits a human name into individual parts. This is useful when dealing with external data sources that provide names as a sing

James Polera 36 May 26, 2022
⚙️ Convert HTML to Markdown. Even works with entire websites and can be extended through rules.

html-to-markdown Convert HTML into Markdown with Go. It is using an HTML Parser to avoid the use of regexp as much as possible. That should prevent so

Johannes Kaufmann 366 Jun 24, 2022
omniparser: a native Golang ETL streaming parser and transform library for CSV, JSON, XML, EDI, text, etc.

omniparser Omniparser is a native Golang ETL parser that ingests input data of various formats (CSV, txt, fixed length/width, XML, EDI/X12/EDIFACT, JS

JF Technology 462 Jun 22, 2022