unit: github.com/ctessum/unit Index | Files | Directories

package unit

import "github.com/ctessum/unit"

Package unit provides a set of types and constants that facilitate the use of the International System of Units (SI).

Unit provides two main functionalities.

1) It provides a number of types representing either an SI base unit or a common combination of base units, named for the unit it represents (Length, Mass, Pressure, etc.). Each type has a float64 as the underlying unit, and its value represents the number of that underlying unit (Kilogram, Meter, Pascal, etc.). For example,

height := 1.6 * unit.Meter
acc := unit.Acceleration(9.8)

creates a variable named 'height' with a value of 1.6 meters, and a variable named 'acc' with a value of 9.8 meters per second squared. These types can be used to add compile-time safety to code. For example,

func UnitDensity(t unit.Temperature, pressure unit.Pressure) (unit.Density){
func main(){
	t := 300 * unit.Kelvin
	p := 5 * unit.Bar
	rho := UnitDensity(p, t) // gives compile-time error

gives a compile-time error (temperature type does not match pressure type) while the corresponding code using float64 runs without error.

func Float64Density(temperature, pressure float64) (float64){
func main(){
	t := 300.0 // degrees kelvin
	p := 50000.0 // Pascals
	rho := Float64Density(p, t) // no error

Many types have constants defined representing named SI units (Meter, Kilogram, etc. ) or SI derived units (Bar, Milligram, etc.). These are all defined as multiples of the base unit, so, for example, the following are euqivalent

l := 0.001 * unit.Meter
k := 1 * unit.Millimeter
j := unit.Length(0.001)

2) Unit provides the type "Unit", meant to represent a general dimensional value. unit.Unit can be used to help prevent errors of dimensionality when multiplying or dividing dimensional numbers. This package also provides the "Uniter" interface which is satisfied by any type which can be converted to a unit. New varibles of type Unit can be created with the New function and the Dimensions map. For example, the code

acc := New(9.81, Dimensions{LengthDim:1, TimeDim: -2})

creates a variable "acc" which has a value of 9.81 m/s^2. Methods of unit can be used to modify this value, for example:

acc.Mul(1.0 * unit.Kilogram).Mul(1 * unit.Meter)

To convert the unit back into a typed float64 value, the From methods of the dimensional types should be used. From will return an error if the dimensions do not match.

var energy unit.Energy
err := (*energy).From(acc)

Domain-specific problems may need custom dimensions, and for this purpose NewDimension should be used to help avoid accidental overlap between packages. For example, results from a blood test may be measured in "White blood cells per slide". In this case, NewDimension should be used to create a 'WhiteBloodCell' dimension. NewDimension takes in a string which will be used for printing that dimension, and will return a unique dimension number. NewDimension should not be used, however, to create the unit of 'Slide', because in this case slide is just a measurement of area. Instead, a constant could be defined.

const Slide unit.Area =  0.001875 // m^2
var WhiteBloodCellDim unit.Dimension
func init(){
	WhiteBloodCellDim = unit.NewDimension("wbc")
type WbcPerArea float64
func (w WbcPerArea) Unit() *Unit{
	return unit.New(float64(w), unit.Dimensions{WhiteBloodCellDim: 1, unit.LengthDim: -2})
func main(){
	v := WbcPerArea(15)
	fmt.Println(v.Unit()) // prints: 1.5e+01 m^-2 wbc

Please note that Unit cannot catch all errors related to dimensionality. Different physical ideas are sometimes expressed with the same dimensions and Unit is incapable of catching these mismatches. For example, energy and torque are both expressed as force times distance (Newton-meters in SI), but it is wrong to say that a torque of 10 N-m is the same as 10 J, even though the dimensions agree.


Package Files

dimensions.go doc.go unit.go


var (
    // Dimless is for dimensionless numbers.
    Dimless = Dimensions{}
    // Joule is a unit of energy [kg m2 s-2]
    Joule = Dimensions{
        MassDim:   1,
        LengthDim: 2,
        TimeDim:   -2,
    // Meter is a meter.
    Meter = Dimensions{
        LengthDim: 1,
    // Meter2 is a square meter
    Meter2 = Dimensions{
        LengthDim: 2,
    // Meter3 is a cubic meter
    Meter3 = Dimensions{
        LengthDim: 3,
    // Meter3PerSecond is a cubic meter per second.
    Meter3PerSecond = Dimensions{
        LengthDim: 3,
        TimeDim:   -1,

    // Kelvin is a degree kelvin [K].
    Kelvin = Dimensions{
        TemperatureDim: 1,

    // KilogramPerMeter3 is density.
    KilogramPerMeter3 = Dimensions{
        MassDim:   1,
        LengthDim: -3,
    // Pascal is a unit of pressure [kg m-1 s-2]
    Pascal = Dimensions{
        MassDim:   1,
        LengthDim: -1,
        TimeDim:   -2,
    // Kilogram is a kilogram.
    Kilogram = Dimensions{
        MassDim: 1,
    // Watt is a unit of power [kg m2 s-3]
    Watt = Dimensions{
        MassDim:   1,
        LengthDim: 2,
        TimeDim:   -3,
    // Herz is a unit of frequency [s-1]
    Herz = Dimensions{
        TimeDim: -1,
    // Second is a second (time).
    Second = Dimensions{
        TimeDim: 1,
    // MeterPerSecond is speed.
    MeterPerSecond = Dimensions{
        TimeDim:   -1,
        LengthDim: 1,
    // MeterPerSecond2 is acceleration.
    MeterPerSecond2 = Dimensions{
        TimeDim:   -2,
        LengthDim: 1,

func DimensionsMatch Uses

func DimensionsMatch(a, b *Unit) bool

DimensionsMatch checks if the dimensions of two *Units are the same.

type Dimension Uses

type Dimension int

Dimension is a type representing an SI base dimension or other orthogonal dimension. If a new dimension is desired for a domain-specific problem, NewDimension should be used. Integers should never be cast as type dimension

// Good: Create a package constant with an init function
var MyDimension unit.Dimension
	MyDimension = NewDimension("my")
	var := MyDimension(28.2)
const (

    // CurrentDim is the dimmension representing current.
    CurrentDim Dimension
    // LengthDim is the dimension representing length.
    // LuminousIntensityDim is the dimension representing luminous intensity
    // MassDim is the dimension representing mass
    // TemperatureDim is the dimension representing temperature
    // TimeDim is the dimension representing time.
    // AngleDim is the dimension representing angle.

func NewDimension Uses

func NewDimension(symbol string) Dimension

NewDimension returns a new dimension variable which will have a unique representation across packages to prevent accidental overlap. The input string represents a symbol name which will be used for printing Unit types. This symbol may not overlap with any of the SI base units or other symbols of common use in SI ("kg", "J", "μ", etc.). A list of such symbols can be found at http://lamar.colostate.edu/~hillger/basic.htm or by consulting the package source. Furthermore, the provided symbol is also forbidden from overlapping with other packages calling NewDimension. NewDimension is expecting to be used only during initialization, and as such it will panic if the symbol matching an existing symbol NewDimension should only be called for unit types that are actually orthogonal to the base dimensions defined in this package. Please see the package-level documentation for further explanation. Calls to NewDimension are not thread safe.

func (Dimension) String Uses

func (d Dimension) String() string

type Dimensions Uses

type Dimensions map[Dimension]int

Dimensions represent the dimensionality of the unit in powers of that dimension. If a key is not present, the power of that dimension is zero. Dimensions is used in conjuction with New.

func (Dimensions) Matches Uses

func (d Dimensions) Matches(d2 Dimensions) bool

Matches checks if the two sets of dimensions are the same.

func (Dimensions) String Uses

func (d Dimensions) String() string

type Unit Uses

type Unit struct {
    // contains filtered or unexported fields

Unit is a type a value with generic SI units. Most useful for translating between dimensions, for example, by multiplying an acceleration with a mass to get a force. Please see the package documentation for further explanation.

func Add Uses

func Add(u ...*Unit) *Unit

Add adds the function arguments. It panics if the units of the arguments don't match. Any nil values are assumed to equal zero.

func Div Uses

func Div(u ...*Unit) *Unit

Div divides the function arguments with the first arguement as the numerator and the rest as the denominator, calculating the proper units for the result. Nil arguments cause a panic.

func Max Uses

func Max(u ...*Unit) *Unit

Max returns the maximum among function arguments. It panics if the units of the arguments don't match. Any nil values are ignored.

func Min Uses

func Min(u ...*Unit) *Unit

Min returns the minimum among function arguments. It panics if the units of the arguments don't match. Any nil values are ignored.

func Mul Uses

func Mul(u ...*Unit) *Unit

Mul multiplies the function arguments, calculating the proper units for the result. Nil arguments cause a panic.

func Negate Uses

func Negate(u *Unit) *Unit

Negate multiplies the value by -1, returning a copy of the input argument.

func New Uses

func New(value float64, d Dimensions) *Unit

New creates a new variable of type Unit which has the value specified by value and the dimensions specified by the base units struct. The value is always in SI Units.

Example: To create an acceleration of 3 m/s^2, one could do myvar := CreateUnit(3.0, &Dimensions{unit.LengthDim: 1, unit.TimeDim: -2})

func Sub Uses

func Sub(u ...*Unit) *Unit

Sub subtracts the second-through-last function arguments from the first function argument. It panics if the units of the arguments don't match. Nil arguments cause a panic.

func (*Unit) Add Uses

func (u *Unit) Add(uu *Unit)

Add adds uu to u, modifying u instead of creating a copy.

func (*Unit) Check Uses

func (u *Unit) Check(d Dimensions) error

Check checks whether u's dimensions match d, and returns an error if they don't.

func (*Unit) Clone Uses

func (u *Unit) Clone() *Unit

Clone makes a copy of a unit.

func (*Unit) Dimensions Uses

func (u *Unit) Dimensions() Dimensions

Dimensions returns the dimenstions associated with the unit.

func (*Unit) Div Uses

func (u *Unit) Div(uu *Unit)

Div divides u by uu, modifying u instead of creating a copy.

func (*Unit) Format Uses

func (u *Unit) Format(fs fmt.State, c rune)

Format makes Unit satisfy the fmt.Formatter interface. The unit is formatted with dimensions appended. If the power if the dimension is not zero or one, symbol^power is appended, if the power is one, just the symbol is appended and if the power is zero, nothing is appended. Dimensions are appended in order by symbol name with positive powers ahead of negative powers.

func (*Unit) Mul Uses

func (u *Unit) Mul(uu *Unit)

Mul multiplies u by uu, modifying u instead of creating a copy.

func (*Unit) Negate Uses

func (u *Unit) Negate()

Negate multiplies u by -1, modifying u instead of creating a copy.

func (*Unit) Sub Uses

func (u *Unit) Sub(uu *Unit)

Sub subtracts uu from u, modifying u instead of creating a copy.

func (*Unit) Value Uses

func (u *Unit) Value() float64

Value return the raw value of the unit as a float64. Use of this method is, in general, not recommended, though it can be useful for printing. Instead, the From type of a specific dimension should be used to guarantee dimension consistency.



Package unit imports 3 packages (graph) and is imported by 9 packages. Updated 2016-07-24. Refresh now. Tools for package owners.