func (vin VIN) Valid() bool {
	matched, err := regexp.MatchString(`^[A-HJ-NPR-Z0-9]{17}$`, vin.String())
	if err != nil {
		return false
	}
	return matched
}
Carry out VIN validation. A valid [number] must be 17 characters long and contain only valid alphanumeric characters.
package govin
import (
	"log"
	"regexp"
	"strings"
	"time"
	"github.com/opencars/vin-decoder-api/pkg/store"
)
const chars = "ABCDEFGHIJKLMNOPRSTUVWXYZ1234567890"
const yearSym = "ABCDEFGHJKLMNPRSTVWXY123456789"
var weights = []int{8, 7, 6, 5, 4, 3, 2, 10, 0, 9, 8, 7, 6, 5, 4, 3, 2}
func Parse(number string) (*VIN, error) {
	value := Normalize(number)
	return &VIN{
		wmi: value[0:3],
		vds: value[3:9],
		vis: value[9:17],
	}, nil
}
type VIN struct {
	wmi string  
	vds string  
	vis string  
}
type Region string
const (
	Africa       Region = "Africa"
	Asia         Region = "Asia"
	Europe       Region = "Europe"
	NorthAmerica Region = "North America"
	Oceania      Region = "Oceania"
	SouthAmerica Region = "South America"
)
func IndexOf(lexeme string) int {
	return strings.IndexByte(chars, lexeme[0])*len(chars) + strings.IndexByte(chars, lexeme[1])
}
func (vin *VIN) WMI() string {
	return vin.wmi
}
func (vin *VIN) VDS() string {
	return vin.vds
}
func (vin *VIN) VIS() string {
	return vin.vis
}
func (vin *VIN) String() string {
	return vin.wmi + vin.vds + vin.vis
}
func (vin VIN) Region() Region {
	region := vin.wmi[0]
	switch {
	case region >= 'A' && region <= 'H':
		return Africa
	case region >= 'J' && region <= 'R':
		return Asia
	case region >= 'S' && region <= 'Z':
		return Europe
	case region >= '1' && region <= '5':
		return NorthAmerica
	case region >= '6' && region <= '7':
		return Oceania
	case region >= '8' && region <= '9':
		return SouthAmerica
	}
	return "Unknown"
}